Python 中 raise 和 raise/from 的区别

本文主要介绍Python中raise与raise..from的区别。通过代码比较和用法解释可知,raise只显示错误类型,异常信息提示处理上一异常时发生新异常;raise..from还显示错误原因,提示上一异常是下一异常的直接原因,且可抑制异常上下文信息。

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__ 属性,不会自动显示异常上下文信息。
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值