Python"正确方法"中的通用异常处理
时间:2020-03-06 14:40:57 来源:igfitidea点击:
有时我发现自己想执行几个顺序命令,例如:
try:
foo(a, b)
except Exception, e:
baz(e)
try:
bar(c, d)
except Exception, e:
baz(e)
...
当仅需要忽略异常时,也会发生相同的模式。
这让人感到多余,语法过多,导致在阅读代码时很难遵循。
在C语言中,我可以使用宏轻松解决这种类型的问题,但是不幸的是,这无法在纯Python中完成。
问题:遇到这种模式时,如何最好地减少代码占用空间并提高代码可读性?
解决方案
如果它们是简单的单行命令,则可以将它们包装在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)),
])
我发现最好的方法是定义一个像这样的函数:
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)
在特定情况下,我们可以执行以下操作:
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)
如果我们使用的是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)
我们可以尝试这样的事情。这模糊地类似于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 )
如果总是这样,则总是在特定函数引发异常时所需的行为,我们可以使用装饰器:
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

