在一行中捕获多个异常(除了块)

我知道我能做到:

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

我也可以这样做:

try:# do something that may failexcept IDontLikeYouException:# say pleaseexcept YouAreTooShortException:# stand on a ladder

但是如果我想在两个不同的例外中做同样的事情,我现在能想到的最好的方法就是这样做:

try:# do something that may failexcept IDontLikeYouException:# say pleaseexcept YouAreBeingMeanException:# say please

有没有办法我可以做这样的事情(因为在两个异常中采取的操作都是say please):

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

现在这真的行不通,因为它匹配以下语法:

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

所以,我捕捉这两个不同例外的努力并没有完全实现。

有办法做到这一点吗?

1311288 次浏览

python文档

除了子句可以将多个异常命名为带括号的元组,例如

except (IDontLikeYouException, YouAreBeingMeanException) as e:pass

或者,仅针对Python 2:

except (IDontLikeYouException, YouAreBeingMeanException), e:pass

用逗号将异常与变量分开在Python 2.6和2.7中仍然有效,但现在已弃用并且在Python 3中不起作用;现在您应该使用as

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

这样做:

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 necessarysys.exit(0)

我只指定这些异常以避免隐藏错误,如果我遇到错误,我希望从完整的堆栈跟踪。

这是记录在这里:https://docs.python.org/tutorial/errors.html

您可以将异常分配给一个变量,(e很常见,但如果您的异常处理很长,或者您的IDE只突出显示比这大的选择,您可能更喜欢更详细的变量,就像我的一样。)实例有一个args属性。这是一个例子:

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

请注意,在Python 3中,当except块结束时,err对象超出范围。

已弃用

您可能会看到用逗号分配错误的代码。这种用法是Python 2.5及更早版本中唯一可用的形式,不建议使用,如果您希望您的代码在Python 3中向前兼容,您应该更新语法以使用新形式:

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

如果您在代码库中看到逗号名称分配,并且您使用的是Python 2.5或更高版本,请切换到新的方式,以便您的代码在升级时保持兼容。

suppress上下文管理器

接受的答案实际上是至少4行代码:

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

tryexceptpass行可以在抑制上下文管理器,在Python 3.4中可用的单行中处理:

from contextlib import suppress
with suppress(IDontLikeYouException, YouAreBeingMeanException):do_something()

因此,当您想在某些例外情况下pass时,请使用suppress

Python留档->8.3处理异常

一个try语句可以有多个除了子句,以指定不同异常的处理程序。最多一个处理程序将是已执行。处理程序仅处理对应的try子句,不在同一try的其他处理程序中语句。除外子句可以将多个异常命名为带括号的元组,例如:

except (RuntimeError, TypeError, NameError):pass

请注意,此元组周围的括号是必需的,因为除了ValueError, e:是用于通常情况下的语法在现代Python中写成except ValueError as e:(描述旧的语法仍然支持向后兼容。这意味着except RuntimeError, TypeError不等于except (RuntimeError, TypeError):但是except RuntimeError asTypeError:这不是你想要的。

做到这一点的方法之一是…

try:You do your operations here;......................except(Exception1[, Exception2[,...ExceptionN]]]):If there is any exception from the given exception list,then execute this block.......................else:If there is no exception then execute this block.

另一种方法是创建执行except块执行的任务的方法,并通过您编写的所有except块调用它。

try:You do your operations here;......................except Exception1:functionname(parameterList)except Exception2:functionname(parameterList)except Exception3:functionname(parameterList)else:If there is no exception then execute this block.
def functionname( parameters )://your task..return [expression]

我知道第二种方法不是最好的方法,但我只是展示了一些方法来做这件事。

如果您经常使用大量异常,您可以预先定义一个元组,因此您不必多次重新键入它们。

#This example code is a technique I use in a library that connects with websites to gather data
ConnectErrs  = (URLError, SSLError, SocketTimeoutError, BadStatusLine, ConnectionResetError)
def connect(url, data):#do connection and return some datareturn(received_data)
def some_function(var_a, var_b, ...):try: o = connect(url, data)except ConnectErrs as e:#do the recovery stuffblah #do normal stuff you would do if no exception occurred

注:

  1. 如果您还需要捕获预定义的元组,您将需要定义另一个除了块。

  2. 如果你不能容忍全局变量,请在main()中定义它并在需要的地方传递…

从Python 3.11开始,您可以利用用于处理多个异常的except*子句。

PEP-654引入了一种新的标准异常类型,称为ExceptionGroup,它对应于一组一起传播的异常。可以使用新的except*语法处理ExceptionGroup*符号表示每个except*子句可以处理多个异常。


例如,您可以处理多个异常

try:raise ExceptionGroup('Example ExceptionGroup', (TypeError('Example TypeError'),ValueError('Example ValueError'),KeyError('Example KeyError'),AttributeError('Example AttributeError')))except* TypeError:...except* ValueError as e:...except* (KeyError, AttributeError) as e:...

有关详细信息,请参阅PEP-654