Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的通用异常处理;“正确的道路”;_Python_Exception_Readability - Fatal编程技术网

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年的习惯。不会很快改变,以消除()附近的空格。需要为老化的基础设施(主要是眼睛)预留空间的习惯决定了我们的可读性。其他的老眼睛会发现空间会因为其他习惯而分散注意力。