32

有时我发现自己处于想要执行几个顺序命令的情况,例如:

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

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

这感觉是多余的,过多的语法导致阅读代码时难以理解。

在 C 语言中,我可以使用宏轻松解决此类问题,但不幸的是,这不能在直接 python 中完成。

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

4

6 回答 6

73

如果您有 python 2.5 或更高版本,则可以使用该with语句:

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)
于 2008-09-24T19:05:58.007 回答
15

如果在特定函数引发异常时始终是您想要的行为,则可以使用装饰器:

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
于 2008-09-25T13:31:32.513 回答
4

如果它们是简单的单行命令,您可以将它们包装在lambdas 中:

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)),
])
于 2008-09-24T19:04:59.803 回答
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)
于 2008-09-24T19:05:17.227 回答
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 )
于 2008-09-24T20:15:09.993 回答
-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)
于 2008-09-24T19:05:48.800 回答