如何在一行中捕获多个异常?(在“except”块中)
- 2024-12-09 08:30:00
- admin 原创
- 145
问题描述:
我知道我能做到:
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
因此,我捕捉这两个不同异常的努力并没有完全成功。
有办法吗?
解决方案 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:
如何在一行中捕获多个异常(除块外)
这样做:
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
这很常见,但如果您的异常处理很长,或者您的 IDE 只突出显示大于该范围的选择,您可能更喜欢更详细的变量,就像我的一样)。该实例具有 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
可以使用 Python 3.4 中的 suppress 上下文管理器在一行中处理try
、except
、行:pass
from contextlib import suppress
with suppress(IDontLikeYouException, YouAreBeingMeanException):
do_something()
因此,当您想要pass
处理某些例外情况时,请使用suppress
。
解决方案 3:
来自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:
等同于不是您想要的。
解决方案 4:
如果频繁使用大量异常,可以预先定义一个元组,这样就不必多次重新输入它们。
#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
笔记:
如果您还需要捕获预定义元组之外的其他异常,则需要定义另一个 except 块。
如果您无法容忍全局变量,请在 main() 中定义它并将其传递到需要的地方......
解决方案 5:
实现此目的的方法之一是..
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]
我知道第二种方法不是最好的方法,但我只是展示了几种方法。
解决方案 6:
从 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。