我知道我可以做到:

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

所以,我试图抓住这两个截然不同的例外并没有成功。

有办法做到这一点吗?


当前回答

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

PEP-654引入了一种新的标准异常类型,称为ExceptionGroup,它对应于一起传播的一组异常。ExceptionGroup可以使用新的except*语法进行处理。*符号表示每个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。

其他回答

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

#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 data
    return(received_data)

def some_function(var_a, var_b, ...):
    try: o = connect(url, data)
    except ConnectErrs as e:
        #do the recovery stuff
    blah #do normal stuff you would do if no exception occurred

笔记:

如果您还需要捕获除预定义的元组,您将需要定义除块之外的另一个块。如果您不能容忍全局变量,请在main()中定义它在需要的地方传递。。。

这样做的方法之一是。。

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块执行的任务,并通过您编写的所有exception块调用它。。

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]

我知道第二种方法不是最好的方法,但我只是展示了很多方法。

从Python文档->8.3处理异常:

try语句可以有多个except子句,以指定不同异常的处理程序。最多有一个处理程序执行。处理程序仅处理发生在对应的try子句,而不是在同一try的其他处理程序中陈述except子句可以将多个异常命名为带括号的元组,例如:除外(RuntimeError、TypeError、NameError):通过请注意,此元组周围的括号是必需的,因为除了ValueError,e:是用于正常情况的语法在现代Python中,除了ValueError外,还将其写为e:(已描述下面)。为了向后兼容,仍然支持旧语法。这意味着除了RuntimeError之外,TypeError与except(RuntimeError,TypeError):但要将RuntimeError作为TypeError:这不是您想要的。

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

执行以下操作:

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

由于使用逗号将错误对象分配给名称的旧语法,括号是必需的。as关键字用于赋值。您可以为错误对象使用任何名称,我个人更喜欢错误。

最佳实践

要以当前和向前兼容Python的方式执行此操作,您需要用逗号分隔异常,并用括号将其括起来,以区别于先前的语法,该语法通过跟随要用逗号捕获的异常类型将异常实例分配给变量名。

下面是一个简单用法的示例:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
    sys.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 err
    print err.args
    sys.exit(0)

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

抑制上下文管理器

公认的答案是至少4行代码:

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

try,except,pass行可以在Python 3.4中使用suppress上下文管理器在一行中处理:

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

因此,当您想要传递某些异常时,请使用suppress。

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

PEP-654引入了一种新的标准异常类型,称为ExceptionGroup,它对应于一起传播的一组异常。ExceptionGroup可以使用新的except*语法进行处理。*符号表示每个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。