有时我发现自己处于需要执行多个顺序命令的情况:
try:
foo(a, b)
except Exception, e:
baz(e)
try:
bar(c, d)
except Exception, e:
baz(e)
...
当需要忽略异常时,会出现同样的模式。
这感觉多余,而且过多的语法使得在阅读代码时难以理解。
在C中,我很容易用宏来解决这类问题,但不幸的是,这不能用直接的python来完成。
问题:遇到这种模式时,如何最好地减少代码占用空间并提高代码可读性?
答案 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)