Python中的通用异常处理;“正确的道路”;
有时,我发现自己处于这样一种情况:我想执行几个顺序命令,如:Python中的通用异常处理;“正确的道路”;,python,exception,readability,Python,Exception,Readability,有时,我发现自己处于这样一种情况:我想执行几个顺序命令,如: try: foo(a, b) except Exception, e: baz(e) try: bar(c, d) except Exception, e: baz(e) ... def handle_exception(function, reaction, *args, **kwargs): try: result = function(*args, **kwargs)
try:
foo(a, b)
except Exception, e:
baz(e)
try:
bar(c, d)
except Exception, e:
baz(e)
...
def handle_exception(function, reaction, *args, **kwargs):
try:
result = function(*args, **kwargs)
except Exception, e:
result = reaction(e)
return result
当需要忽略异常时,也会出现同样的模式
这感觉是多余的,过多的语法导致阅读代码时令人惊讶地难以理解
在C语言中,我可以用宏轻松地解决这类问题,但不幸的是,用纯python无法做到这一点
问题:遇到这种模式时,如何才能最好地减少代码占用并提高代码可读性?如果它们是简单的单行命令,您可以将它们包装在
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)),
])
我发现最好的方法是定义如下函数:
try:
foo(a, b)
except Exception, e:
baz(e)
try:
bar(c, d)
except Exception, e:
baz(e)
...
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或更高版本,则可以使用:
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 )
如果在特定函数引发异常时,这始终是您想要的行为,那么您可以使用decorator:
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
您可以通过返回而不是赋值给“result”来简化该函数。如果foo()引发异常,则不会执行bar()。这不是你想要的行为。你的间隔太可怕了。请参阅“表达式和语句中的空白”而不是“可怕”。惯用的和非典型的。从Pascal和C开始有30年的习惯。不会很快改变,以消除()附近的空格。需要为老化的基础设施(主要是眼睛)预留空间的习惯决定了我们的可读性。其他的老眼睛会发现空间会因为其他习惯而分散注意力。