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

Catch multiple exceptions in one line (except block)

提问人:inspectorG4dget 提问时间:6/24/2011 最后编辑:inspectorG4dget 更新时间:3/23/2023 访问量:1431713

问:

我知道我可以做到:

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

有什么方法可以做这样的事情(因为在两个例外中要采取的行动是):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 异常

评论

42赞 gerrit 4/17/2019
请注意,在 Python 3 中,后者不再是有效的语法。
2赞 royce3 10/31/2022
您的第一个代码片段触发了我一点 - 请参阅 wilfred.me.uk/blog/2013/11/03/no-naked-excepts

答:

5045赞 mechanical_meat 6/24/2011 #1

来自 Python 文档

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

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

或者,仅适用于 Python 2:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

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

评论

2赞 BallpointBen 3/22/2018
是否可以将所需的异常存储在可迭代对象中,然后捕获可迭代对象?我正在尝试使用 将警告列表转换为错误,并且我不想必须两次指定警告列表。warnings.filterwarnings
31赞 BallpointBen 3/23/2018
我确实试过了......与 ,它导致了 .看起来错误必须位于 中,才能按预期进行捕获。listTypeErrortuple
16赞 BallpointBen 3/23/2018
目前尚不清楚“括号元组”是否仅仅是句法上的,还是需要一个真正的元组。“括号”具有误导性,因为您可能会在其他地方创建一个不带括号的元组,然后在行中使用它。只有在行中创建时,它才必须用括号括起来。exceptexcept
8赞 jammertheprogrammer 4/12/2019
@JosephBani,生成器表达式呢?
42赞 Soren Bjornstad 7/13/2019
@JosephBani 这根本不是真的。在 中,当然不是元组。括号是一种常规分组结构。元组的定义特征是它包含一个逗号——参见 Python 文档:“请注意,实际上是逗号组成了一个元组,而不是括号。2 + (x * 2)(x * 2)
519赞 Russia Must Remove Putin 6/21/2014 #2

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

执行此操作:

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

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

最佳实践

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

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

import sys

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

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

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

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

import sys

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

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

荒废的

您可能会看到用逗号分配错误的代码。此用法是 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

可以使用 Python 3.4 中提供的 suppress 上下文管理器在一行中处理 , , 行:tryexceptpass

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

因此,当您想要对某些例外情况进行时,请使用 .passsuppress

评论

27赞 Mache 12/17/2019
很好的补充,比只是在上做更具可读性suppresspassexcept
0赞 An old man in the sea. 2/14/2023
您可以记录异常,然后将其传递到 with 上下文管理器之外吗?
72赞 fedorqui 10/30/2014 #3

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

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

except (RuntimeError, TypeError, NameError):
    pass

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

34赞 M.Usman 8/17/2017 #4

其中一种方法是..

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. 

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

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]

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

评论

2赞 chizou 7/2/2019
我之所以使用第二个,是因为我有两个不同的异常,每个例外都需要以不同的方式处理。这样做有什么问题吗?
3赞 Eponymous 8/14/2019
@majikman 第二种方法具有多个子句,每个子句调用相同的函数,当您试图不重复自己并对两个异常执行相同的操作时,这不是最好的方法。(有关正确的方法,请参阅其他答案)。但是,当您想要以不同的方式处理异常时,具有多个子句是正常的。except
0赞 étale-cohomology 12/10/2021
第二种方式其实很棒
60赞 whitebeard 9/18/2017 #5

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

#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

笔记:

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

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

18赞 Giorgos Myrianthous 4/2/2022 #6

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

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