raise 与raise..from的区别主要在于:
在显示错误信息时,raise只显示错误类型,raise...from...还会显示导致错误的原因(原因是from 后面的部分)。
以下转自:https://blog.youkuaiyun.com/jpch89/article/details/84315444#Python__raise__raisefrom__0
文章目录
Python 中 raise 和 raise/from 的使用方法
0. 参考资料
1. 代码比较
2. 用法解释
2.1 raise
2.2 raise A from B
3. 总结
0. 参考资料
Python “raise from” usage
The raise statement
Built-in Exceptions
1. 代码比较
今天在看《Effective Python》的时候第一次见到 raise A from B 的用法,所以在网上查了一下。
下面用代码比较一下 raise 和 raise/from 的区别。
raise.py
# raise
try:
raise ValueError
except Exception as e:
raise IndexError
错误输出为:
"""
Traceback (most recent call last):
File "raise.py", line 3, in <module>
raise ValueError
ValueError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "raise.py", line 5, in <module>
raise IndexError
IndexError
"""
raisefrom.py
# raise/from
try:
raise ValueError
except Exception as e:
raise IndexError from e
错误输出为:
"""
Traceback (most recent call last):
File "raisefrom.py", line 3, in <module>
raise ValueError
ValueError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "raisefrom.py", line 5, in <module>
raise IndexError from e
IndexError
"""
错误输出比较:
# raise.py
"""
Traceback (most recent call last):
File "raise.py", line 3, in <module>
raise ValueError
ValueError
During handling of the above exception, another exception occurred:
## 处理以上异常时,发生另一个异常
Traceback (most recent call last):
File "raise.py", line 5, in <module>
raise IndexError
## 发出异常的语句
IndexError
"""
##----------------------------------------------------------------##
# raisefrom.py
"""
Traceback (most recent call last):
File "raisefrom.py", line 3, in <module>
raise ValueError
ValueError
The above exception was the direct cause of the following exception:
## 上面的异常由下面的异常直接导致
Traceback (most recent call last):
File "raisefrom.py", line 5, in <module>
raise IndexError from e
## 发出异常的语句
IndexError
"""
根据比较可见,异常输出主要有两个地方不一样(用汉语做注释的地方),其中有意义的不同是两个异常关系的描述,后者指出了两个异常之间的关联关系。
上面的 raise 和 raise/from 都是放在 except 异常处理块中的。
可以观察到 raise 和 raise/from 最大的区别是异常提示信息不一样:
raise 是:During handling of the above exception, another exception occurred:。
即“在处理上面的异常时,发生了另外一个异常:”。
而 raise/from 是:The above exception was the direct cause of the following exception:。
即“上面的异常是接下来的异常的直接原因:”。
2. 用法解释
2.1 raise
当在 except 块或者 finally 块中出现异常时(包括使用单独的 raise 重新抛出异常的情况),之前的异常会被附加到新异常的 __context__ 属性上。
except 块中的语句叫做异常处理器 exception handler,它们是处理异常的语句。
而在其他任何地方抛出异常,都不会设置 __context__ 属性。
这样打印出来的异常信息就会包含这么一句话:During handling of the above exception, another exception occurred:。
2.2 raise A from B
raise A from B 语句用于连锁 chain 异常。
from 后面的 B 可以是:
异常类
异常实例
None(Python 3.3 的新特性)
如果 B 是异常类或者异常实例,那么 B 会被设置为 A 的 __cause__ 属性,表明 A异常 是由 B异常 导致的。
这样打印出来的异常信息就会包含这样一句话:The above exception was the direct cause of the following exception:。
与此同时,在 Python 3.3 中 A异常 的 __suppress_context__ 属性会被设置为 True,这样就抑制了 A异常 的 __context__ 属性,即忽略 __context__ 属性。
于是 Python 就不会自动打印异常上下文 exception context,而是使用 __cause__ 属性来打印异常的引发者。
在 Python 3.3 中,B 还可以是 None:raise A异常 from None。
这样相当于把 __suppress_context__ 属性设置为 True,从而禁用了 __context__ 属性,Python 不会自动展示异常上下文。
比如下面这段代码,注意到只显示了 IndexError 一个异常信息:
raisefromnone.py
# raise ... from None
# 禁用异常上下文属性
try:
raise ValueError
except Exception as e:
raise IndexError from None
"""
Traceback (most recent call last):
File "raisefromnone.py", line 6, in <module>
raise IndexError from None
IndexError
"""
3. 总结
在 except 或者 finally 块中使用 raise 和 raise/from 语句需要注意:
raise 会设置后面异常的 __context__ 属性为前面的异常。
异常信息中会有 During handling of the above exception, another exception occurred:。
raise A异常 from B异常 会把 A异常 的 __cause__ 属性设置为 B异常。
同时设置 __suppress_context__ 属性为 True,从而忽略 __context__ 属性,不打印异常上下文信息。
异常信息中会有 The above exception was the direct cause of the following exception:。
raise A异常 from None 会设置 A异常 的 __suppress_context__ 属性为 True,这样会忽略它的 __context__ 属性,不会自动显示异常上下文信息。
本文主要介绍Python中raise与raise..from的区别。通过代码比较和用法解释可知,raise只显示错误类型,异常信息提示处理上一异常时发生新异常;raise..from还显示错误原因,提示上一异常是下一异常的直接原因,且可抑制异常上下文信息。
1226

被折叠的 条评论
为什么被折叠?



