簡體   English   中英

在 python 3 中禁用異常鏈接

[英]Disable exception chaining in python 3

python3 中引入了一個新特性——異常鏈接。 由於某些原因,我需要為代碼中的某些異常禁用它。

這是示例代碼:

try:
    print(10/0)
except ZeroDivisionError as e:
    sys.exc_info()
    raise AssertionError(str(e))

我所看到的:

Traceback (most recent call last):
  File "draft.py", line 19, in main
    print(10/0)
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "draft.py", line 26, in <module>
    main()
  File "draft.py", line 22, in main
    raise AssertionError(str(e))
AssertionError: division by zero

我想看到的:

Traceback (most recent call last):
  File "draft.py", line 26, in <module>
    main()
  File "draft.py", line 22, in main
    raise AssertionError(str(e))
AssertionError: division by zero

我嘗試使用sys.exc_clear() ,但此方法也已從 python 3 中刪除。 我可以使用可行的解決方法

exc = None
try:
    print(10/0)
except ZeroDivisionError as e:
    exc = e
if exc:
    raise AssertionError(str(exc))

但我相信有更好的解決方案。

簡單的答案

try:
    print(10/0)
except ZeroDivisionError as e:
    raise AssertionError(str(e)) from None

但是,您可能實際上想要:

try:
    print(10/0)
except ZeroDivisionError as e:
    raise AssertionError(str(e)) from e

解釋

__cause__

當沒有明確的原因異常集時,隱式異常鏈接通過__context__發生。

顯式異常鏈接通過__cause__工作,因此如果您將__cause__設置為異常本身,它應該停止鏈接。 如果設置了__cause__ ,Python 將抑制隱式消息。

try:
    print(10/0)
except ZeroDivisionError as e:
    exc = AssertionError(str(e))
    exc.__cause__ = exc
    raise exc

我們可以使用“raise from”來做同樣的事情:

try:
    print(10/0)
except ZeroDivisionError as e:
    exc = AssertionError(str(e))
    raise exc from exc

沒有__cause__

__cause__設置為None實際上做同樣的事情:

try:
    print(10/0)
except ZeroDivisionError as e:
    exc = AssertionError(str(e))
    exc.__cause__ = None
    raise exc

從無提高

所以這給我們帶來了最優雅的方式來做到這一點,即None提出

try:
    print(10/0)
except ZeroDivisionError as e:
    raise AssertionError(str(e)) from None

但我認為您通常希望從原因異常中顯式引發異常,以便保留回溯:

try:
    print(10/0)
except ZeroDivisionError as e:
    raise AssertionError(str(e)) from e

這將給我們一個稍微不同的消息,指出第一個異常是第二個異常的直接原因:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

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

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
AssertionError: division by zero

python3 中引入了一個新特性——異常鏈接。 由於某些原因,我需要針對代碼中的某些異常禁用它。

這是示例代碼:

try:
    print(10/0)
except ZeroDivisionError as e:
    sys.exc_info()
    raise AssertionError(str(e))

我所看到的:

Traceback (most recent call last):
  File "draft.py", line 19, in main
    print(10/0)
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "draft.py", line 26, in <module>
    main()
  File "draft.py", line 22, in main
    raise AssertionError(str(e))
AssertionError: division by zero

我想看到的:

Traceback (most recent call last):
  File "draft.py", line 26, in <module>
    main()
  File "draft.py", line 22, in main
    raise AssertionError(str(e))
AssertionError: division by zero

我嘗試使用sys.exc_clear() ,但此方法也已從 python 3 中刪除。 我可以使用有效的解決方法

exc = None
try:
    print(10/0)
except ZeroDivisionError as e:
    exc = e
if exc:
    raise AssertionError(str(exc))

但我相信有更好的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM