Python 中 raise 和 raise/from 的使用方法
- 参考资料
- 代码比较
今天在看《Effective Python》的时候第一次见到 raise A from B 的用法,所以在网上查了一下。
下面用代码比较一下 raise 和 raise/from 的区别。
raise.py
1 | python复制代码# raise |
raisefrom.py
1 | python复制代码# raise/from |
上面的 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.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
1 | python复制代码# raise ... from None |
- 总结
在 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__属性,不会自动显示异常上下文信息。
完成于 2018.11.21
本文转载自: 掘金