【Python】(異常機制)raise ... 和 raise ... from ... 的區別和使用



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:


使用

沒有 from 是接近錯誤的使用方式。

比如:

try:
    raise IndexError("in try")
except IndexError as err:
    raise RuntimeError(str(err))

與:

def hanlder_error():
    raise RuntimeError("error by accident")

try:
    raise IndexError("in try")
except IndexError as err:
    hanlder_error()
    raise RuntimeError(str(err)) from err

這是兩段有着不同含義的代碼。

運行結果對比:
n/a

不看錯誤提示消息中的代碼的話,“字面上”是一個意思。

刪掉錯誤提示的代碼之後,提示信息除了有指出第二個 error 發生的所在位置(在函數裏面)之外,提示信息的含義完全一樣:

n/a
這個提示信息的含義都表示:第二個異常是在 except /捕獲異常 內部(再次)發生了異常(During handling of the above exception, another exception occurred)。

但是實際情況是:

  • 第二段代碼確實符合提示的錯誤信息(RuntimeError 是在捕獲 IndexError 異常處理時另外發生的異常)。

  • 第一段完全不是,第一段代碼的第二異常並非是在捕獲異常內部(except 中)再次發生異常,而本意是想將 try 內發生的異常(通過另外一種異常類來表示)向更高級調用拋出。

如果使用 raise ... from ... 則錯誤提示消息含義完全不同:

try:
    raise IndexError("in try")
except IndexError as err:
    raise RuntimeError(str(err)) from err

n/a

當我們看到 The above exception was the direct cause of the following exception 則知道,這句話下面的異常本質上和這句話上面的異常是同一個。這句話下面的異常加上這句話本身表示了該異常來自 try 內部,而非 except 內。

During handling of the above exception, ... 這句表示了這句話下面的異常來自 except 內;即真正意思是表示了此時發生兩個異常

所以我們需要使用 raise ... from ... 這樣的寫法,如果 except 內部真的沒有異常發生的話,錯誤提示也是表達了只有一個異常,這個異常進一步回溯到 try 內部發生的異常。
raise ... 這麼直接編寫的話,雖然在代碼作用上沒有什麼差別,但是含義上有區別,它表示了 try 內部發生了異常,但是在 except 內部處理的時候,又發生了另一個異常;這和實際情況是不符合的。



總結

raise 本身就是拋出異常的作用(含義)。

所以當我們想要在 except 內部拋出另外一個異常,就使用 raise <SomeError>

但是如果我們想要將原本來自 try 內部的異常,在 except繼續(往上)拋出的話,要嘛直接使用 raise,即:

try:
    raise IndexError("in try")
except IndexError as err:
    ...do something...
    raise

又或者我們想要對這個異常換一種異常類(換一種表示異常含義,比如自己定義的異常類等),
那麼就應當使用 raise ... from <last_error_instance>, 即:

try:
    raise IndexError("in try")
except IndexError as err:
    ...do something...
    raise RuntimeError("the right way to continue raise") from err


Reference



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章