Python - 异常链



异常链

异常链是一种通过在新的异常中包装已捕获的异常来重新抛出已捕获异常的异常处理技术。原始异常被保存为新异常的属性(例如 cause)。

在处理一个异常“A”的过程中,另一个异常“B”可能会发生。为了调试问题,了解这两个异常非常有用。有时,异常处理程序故意重新抛出异常很有用,无论是为了提供额外信息还是将异常转换为另一种类型。

在 Python 3.x 中,可以实现异常链。如果在 except 块中存在任何未处理的异常,它将把正在处理的异常附加到它并包含在错误消息中。

示例

在下面的代码片段中,尝试打开一个不存在的文件会引发 FileNotFoundError。except 块检测到它。在处理过程中,另一个异常被引发。

try:
   open("nofile.txt")
except OSError:
   raise RuntimeError("unable to handle error")

它将产生以下输出

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 2, in <module>
open("nofile.txt")
FileNotFoundError: [Errno 2] No such file or directory: 'nofile.txt'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 4, in <module>
    raise RuntimeError("unable to handle error")
RuntimeError: unable to handle error

raise . . from 语句

如果在 raise 语句中使用可选的 from 从句,则表示异常是另一个异常的直接后果。当转换异常时,这很有用。from 关键字后的标记应该是异常对象。

try:
   open("nofile.txt")
except OSError as exc:
   raise RuntimeError from exc

它将产生以下输出

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 2, in <module>
    open("nofile.txt")
FileNotFoundError: [Errno 2] No such file or directory: 'nofile.txt'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/cg/root/64afcad39c651/main.py", line 4, in <module>
    raise RuntimeError from exc
RuntimeError

raise . . from None 语句

如果我们使用 from 从句中的 None 来代替异常对象,则前面示例中找到的自动异常链将被禁用。

try:
   open("nofile.txt")
except OSError as exc:
   raise RuntimeError from None

它将产生以下输出

Traceback (most recent call last):
 File "C:\Python311\hello.py", line 4, in <module>
  raise RuntimeError from None
RuntimeError

__context__ 和 __cause__ 表达式

在 except 块中引发异常会自动将捕获的异常添加到新异常的 __context__ 属性。类似地,您还可以使用表达式raise ... from语法将 __cause__ 添加到任何异常。

try:
   try:
      raise ValueError("ValueError")
   except ValueError as e1:
      raise TypeError("TypeError") from e1
except TypeError as e2:
   print("The exception was", repr(e2))
   print("Its __context__ was", repr(e2.__context__))
   print("Its __cause__ was", repr(e2.__cause__))

它将产生以下输出

The exception was TypeError('TypeError')
Its __context__ was ValueError('ValueError')
Its __cause__ was ValueError('ValueError')
广告
© . All rights reserved.