Python中“正确”的通用异常处理方法

33 投票
6 回答
66682 浏览
提问于 2025-04-11 09:28

有时候,我会遇到想要顺序执行几个命令的情况,比如这样:

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

这种情况也会出现在需要忽略异常的时候。

这样写感觉有点多余,而且过多的语法让代码看起来很难读懂。

在C语言中,我可以很简单地用宏来解决这个问题,但可惜在纯Python中做不到。

问题是:我该如何减少代码的冗余,提升代码的可读性呢?

6 个回答

4

如果它们只是简单的一行命令,你可以用 lambda 来包裹它们:

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)),
])
16

如果你希望在某个特定的函数出现错误时,总是以这种方式处理,那你可以使用一个装饰器:

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
74

如果你使用的是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)

撰写回答