如何在一行中捕获多个异常?(在“except”块中)

3827 投票
6 回答
1464642 浏览
提问于 2025-04-16 20:14

我知道我可以这样做:

try:
    # do something that may fail
except:
    # do this if ANYTHING goes wrong

我也可以这样做:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreTooShortException:
    # stand on a ladder

但是如果我想在两个不同的错误中做同样的事情,我现在想到的最好办法是这样:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreBeingMeanException:
    # say please

有没有办法让我像这样做呢(因为在这两个错误中要做的动作都是说请):

try:
    # do something that may fail
except IDontLikeYouException, YouAreBeingMeanException:
    # say please

现在这样真的行不通,因为它符合以下的语法:

try:
    # do something that may fail
except Exception, e:
    # say please

所以,我想要捕捉这两个不同错误的努力并没有完全成功。

有没有办法做到这一点呢?

6 个回答

73

来自 Python文档 -> 8.3 处理异常:

一个 try 语句可以有多个 except 子句,这样可以为不同的异常指定处理方式。最多只会执行一个处理器。处理器只会处理在对应的 try 子句中发生的异常,而不会处理同一个 try 语句中其他处理器的异常。一个 except 子句可以用一个带括号的元组来列出多个异常,比如:

except (RuntimeError, TypeError, NameError):
    pass

注意,这个元组的括号是必须的,因为 except ValueError, e: 是以前的写法,而现代Python中通常写作 except ValueError as e:(下面会详细说明)。旧的写法仍然被支持,以便与以前的代码兼容。这意味着 except RuntimeError, TypeError 并不等同于 except (RuntimeError, TypeError):,而是等同于 except RuntimeError as TypeError:,这并不是你想要的结果。

525

如何在一行中捕获多个异常(except 块)

这样做:

try:
    may_raise_specific_errors():
except (SpecificErrorOne, SpecificErrorTwo) as error:
    handle(error) # might log or have some other default behavior...

这里的括号是必须的,因为早期的语法使用逗号来给错误对象命名。as 关键字用于赋值。你可以给错误对象起任何名字,我个人喜欢用 error

最佳实践

为了让你的代码在当前和未来的 Python 版本中都能兼容,你需要用逗号分隔异常,并用括号包裹起来,这样可以和早期的语法区分开来。早期的语法是通过在要捕获的异常类型后面加逗号来给异常实例命名的。

这里有个简单的用法示例:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
    sys.exit(0)

我只指定这些异常,以避免隐藏错误。如果我遇到这些错误,我希望能看到完整的错误追踪信息。

相关文档可以在这里找到:https://docs.python.org/tutorial/errors.html

你可以把异常赋值给一个变量,(e 是常用的名字,但如果你的异常处理比较长,或者你的开发环境只高亮大于这个长度的选择,你可能会更喜欢用更详细的变量名。) 这个实例有一个 args 属性。这里是一个示例:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError) as err: 
    print(err)
    print(err.args)
    sys.exit(0)

注意,在 Python 3 中,err 对象在 except 块结束时会失去作用域。

已弃用

你可能会看到一些代码用逗号来给错误赋值。这种用法是 Python 2.5 及更早版本中唯一可用的形式,现在已经被弃用。如果你希望你的代码在 Python 3 中兼容,应该更新语法,使用新的形式:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError), err: # don't do this in Python 2.6+
    print err
    print err.args
    sys.exit(0)

如果你在代码中看到逗号命名赋值,并且你使用的是 Python 2.5 或更高版本,建议你切换到新的写法,这样在升级时你的代码能保持兼容。

suppress 上下文管理器

被接受的答案实际上至少需要 4 行代码:

try:
    do_something()
except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

tryexceptpass 这几行可以用 在 Python 3.4 中可用的 suppress 上下文管理器 一行处理:

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

所以当你想要对某些异常“跳过”时,使用 suppress

5085

来自 Python文档

在处理异常时,你可以在except语句中同时列出多个异常,用括号把它们包起来,比如:

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

另外,对于Python 2来说:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

在Python 2.6和2.7中,用逗号把异常和变量分开也是可以的,但这种写法现在已经不推荐使用,并且在Python 3中不再有效;现在你应该使用 as 这个关键词。

撰写回答