Python中的通用异常处理“正确的方法”

时间:2008-09-24 19:00:48

标签: python exception readability

有时我发现自己处于需要执行多个顺序命令的情况:

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

当需要忽略异常时,会出现同样的模式。

这感觉多余,而且过多的语法使得在阅读代码时难以理解。

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

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

6 个答案:

答案 0 :(得分:68)

如果你有python 2.5

,你可以使用with statement
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)

答案 1 :(得分:14)

如果总是这样,总是当特定函数引发异常时你想要的行为,你可以使用装饰器:

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

答案 2 :(得分: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 :(得分: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)

答案 4 :(得分:3)

你可以尝试这样的事情。这有点模糊C宏。

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 :(得分:-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)