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')
廣告