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


我知道我能做到:

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

因此,我努力捕捉这两个截然不同的例外并没有完全实现。

有没有办法做到这一点?


1963
2018-06-24 15:55


起源




答案:


Python文档

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

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

或者,仅适用于Python 2:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

使用逗号将变量与变量分开仍然可以在Python 2.6和2.7中使用,但现在已弃用,但在Python 3中不起作用;现在你应该使用 as


2712
2018-06-24 15:56



是否可以在迭代中存储所需的异常,然后捕获可迭代的?我正在尝试将警告列表变为错误 warnings.filterwarnings,我不想两次指定警告列表。 - BallpointBen
我确实尝试过...... list,它导致了一个 TypeError。看起来错误必须在 tuple 按预期上班。 - BallpointBen
当你清楚地看到在这种情况下需要一个元组时,为什么你会使用一个列表呢? - bernie
目前还不清楚“带括号的元组”是仅仅是语法还是需要一个真正的元组。 “括号内容”具有误导性,因为您可能会在其他地方创建一个没有括号的元组,然后在其中使用它 except线。如果在。中创建,它只需要括号 except 线。 - BallpointBen


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

做这个:

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

由于较旧的语法使用逗号将错误对象分配给名称,因此必须使用括号。该 as 关键字用于分配。您可以使用任何名称作为错误对象,我更喜欢 error 亲自。

最佳实践

要以当前和向前兼容Python的方式执行此操作,您需要使用逗号分隔异常并用括号括起它们,以区别于将异常实例分配给变量名的早期语法,方法是遵循要捕获的异常类型逗号。

这是一个简单用法的例子:

try:
    mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
    quit(0)

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

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

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

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

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

弃用

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

try:
    mainstuff()
except (KeyboardInterrupt, EOFError), err: # don't do this in Python 2.6+
    print err
    print err.args
    quit(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


186
2018-06-21 04:20



最完整的答案。唯一一个指定如何使用的 except (KeyboardInterrupt, EOFError): 句法。 - Eduard Luca


对于python 2.5及更早版本,正确的语法是:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    print e

哪里 e 是Exception实例。


49
2018-05-13 12:37



如果要转发兼容代码,则不应使用逗号分配e,并且不再更新Python 2.5: mail.python.org/pipermail/python-committers/2011-October/... - Aaron Hall♦
是的,但是使用python 2.5,没有别的办法。解决方案明确说明(旧)版本。 - Jean-François Fabre


Python文档 - > 8.3处理异常

一个 try 声明可以有多个except子句来指定   不同例外的处理程序。最多只有一个处理程序   执行。处理程序只处理发生的异常   相应的try子句,不在同一尝试的其他处理程序中   声明。 except子句可以将多个异常命名为a   带括号的元组,例如:

except (RuntimeError, TypeError, NameError):
    pass

请注意,这个元组周围的括号是必需的,因为   除 ValueError, e: 是通常用于什么的语法   写作 except ValueError as e: 在现代Python中(描述   下面)。仍然支持旧语法以实现向后兼容性。   意即 except RuntimeError, TypeError 不等于    except (RuntimeError, TypeError): 但是 except RuntimeError as TypeError: 这不是你想要的。


37
2017-10-30 10:01





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

#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. 如果你还需要捕获除了那些之外的其他例外 预定义的元组,你需要定义另一个除了块。

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


15
2017-09-18 01:36





其中一种方法是..

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]

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


5
2017-08-17 11:56





Python 2.7文档声明:

try语句可能有多个except子句来指定   不同例外的处理程序。最多只有一个处理程序   执行。处理程序只处理发生的异常   相应的try子句,不在同一尝试的其他处理程序中   声明。 except子句可以将多个异常命名为a   带括号的元组,例如:

try:
    raise ValueError("hello")
except (RuntimeError, ValueError, KeyError) as a:
    print a

注意   这个元组周围的括号是必需的,因为除了   ValueError,e:用于通常写为的语法   除了ValueError为e:在现代Python中(如下所述)。老人   仍支持语法以实现向后兼容性。意即   除了RuntimeError,TypeError不等于except   (RuntimeError,TypeError):但是除了RunErrorError以外的TypeError:   这不是你想要的。


3
2017-12-05 14:05