2008-09-24 40 views
25

有时候,我觉得自己在这里我要执行像这样几个连续的命令的情况:当异常只是需要被忽略时通用异常处理“正道”

try: 
    foo(a, b) 
except Exception, e: 
    baz(e) 
try: 
    bar(c, d) 
except Exception, e: 
    baz(e) 
... 

同样的模式。

这种感觉是多余的,过多的语法会导致它在读取代码时难以遵循。

在C中,我会用宏很容易地解决这类问题,但不幸的是,这不能用直接的python来完成。

问题:在遇到这种模式时,如何最好地减少代码占用量并提高代码可读性?

回答

62

你可以使用with statement如果你有Python 2.5的

from __future__ import with_statement 
import contextlib 

@contextlib.contextmanager 
def handler(): 
    try: 
     yield 
    except Exception, e: 
     baz(e) 

你比如现在变成:

with handler(): 
    foo(a, b) 
with handler(): 
    bar(c, d) 
4

如果他们是简单的一个行命令,你可以在lambda S环绕他们:

for cmd in [ 
    (lambda: foo (a, b)), 
    (lambda: bar (c, d)), 
]: 
    try: 
     cmd() 
    except StandardError, e: 
     baz (e) 

你可以换的是整件事的功能,所以它看起来像这样:

ignore_errors (baz, [ 
    (lambda: foo (a, b)), 
    (lambda: bar (c, d)), 
]) 
3

我发现最好的方法,是定义像这样的功能:

def handle_exception(function, reaction, *args, **kwargs): 
    try: 
     result = function(*args, **kwargs) 
    except Exception, e: 
     result = reaction(e) 
    return result 

但只是不觉得还是看在实践中正确的:

handle_exception(foo, baz, a, b) 
handle_exception(bar, baz, c, d) 
+5

你可以通过仅返回而不是分配给“结果”来简化该功能。 – 2008-09-24 19:06:54

-4

在特定情况下,你可以这样做:

try: 
    foo(a, b) 
    bar(c, d) 
except Exception, e: 
    baz(e) 

或者,你可以捕捉上述异常一步:

try: 
    foo_bar() # This function can throw at several places 
except Exception, e: 
    baz(e) 
+3

如果foo()引发异常,bar()将不会被执行。这不是理想的行为。 – Sufian 2008-09-24 19:10:01

3

你可以尝试这样的事情。这是含糊的宏观状态。

class TryOrBaz(object): 
    def __init__(self, that): 
     self.that= that 
    def __call__(self, *args): 
     try: 
      return self.that(*args) 
     except Exception, e: 
      baz(e) 

TryOrBaz(foo)(a, b) 
TryOrBaz(bar)(c, d) 
+5

你的间距太可怕了。请参阅“表达式和语句中的空格”http://www.python.org/dev/peps/pep-0008/ – jfs 2008-09-25 03:58:50

11

如果这是永远,总是要在一个特定的功能引发了异常,您可以使用一个装饰的行为:

def handle_exception(handler): 
    def decorate(func): 
     def call_function(*args, **kwargs): 
      try: 
       func(*args, **kwargs) 
      except Exception, e: 
       handler(e) 
     return call_function 
    return decorate 

def baz(e): 
    print(e) 

@handle_exception(baz) 
def foo(a, b): 
    return a + b 

@handle_exception(baz) 
def bar(c, d): 
    return c.index(d) 

用法:

>>> foo(1, '2') 
unsupported operand type(s) for +: 'int' and 'str' 
>>> bar('steve', 'cheese') 
substring not found