在python 3中禁用异常链接 [英] Disable exception chaining in python 3
问题描述
python3中引入了一个新功能-异常链接。由于某些原因,我需要为代码中的某些异常禁用它。
以下是示例代码:
try:
print(10/0)
除了ZeroDivisionError如e:
sys.exc_info()
引发AssertionError(str(e) )
我看到的是:
Traceback(最近一次通话):
文件 draft.py,第19行,在主
打印中(10/0)
ZeroDivisionError:除以零
在处理上述异常期间,发生了另一个异常:
追溯(最近一次调用为最后一次):
文件 draft.py,第26行,在< module>中
main()
文件 draft.py,第22行,在主
中,引发AssertionError(str(e))
AssertionError:除以零
我想看的东西:
追踪(最近一次通话最近):
文件 draft.py,第26行,在< module>中
main()
文件 draft.py,第22行,在主
中,引发AssertionError(str(e))
AssertionError:除以零
我尝试使用 sys.exc_clear()
,但是这种方法是也从python 3中删除了。
我可以使用可行的解决方法
exc = None
try:
print(10 / 0)$零元零零零零零零零零零零零零零零零张零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零零年零零零零零零零零零零零零零零零零零零零以下美元/ pre>
,但我相信有更好的解决方案。
解决方案
简单答案
try:
print(10/0)
除了ZeroDivisionError如e:
从无$引发AssertionError(str(e))
但是,您实际上可能想要:
try:
print(10/0)
除了ZeroDivisionError以外,例如e:
提高AssertionError(从e
中的str(e))
解释
< h3> __原因__
隐式异常链接通过 __ context __
发生
显式异常链接通过 __ cause __ $ c起作用$ c>,因此,如果将 __ cause __
设置为异常本身,它将停止链接。如果设置了 __ cause __
,Python将取消隐式消息。
try :
print(10/0)
除了ZeroDivisionError为e:
exc = AssertionError(str(e))
exc .__ cause__ = exc
提高exc
从
我们可以使用从做同样的事情:
try:
print(10/0)
除了ZeroDivisionError为e:
exc = AssertionError(str(e))
从ex
< h3>没有 __原因__
将 __原因__
设置为 None
实际上做同样的事情:
try:
print( 10/0)
除了ZeroDivisionError如e:
exc = AssertionError(str(e))
exc .__ cause__ = None
筹集美元
从无起步
所以这使我们成为了最优雅的方式为此ich要从无
筹集资金:
尝试:
print(10/0)
除了ZeroDivisionError,因为e:
从无
$提高AssertionError(str(e)) p $ p>
但是我认为您通常想从原因异常中显式引发异常,以便保留回溯:
尝试:
print(10/0)
除了ZeroDivisionError,因为e:
从e $ b $引发AssertionError(str(e)) b
这会给我们一个稍微不同的信息,指出第一个例外是第二个例外的直接原因:
Traceback(最近一次通话最近):
文件< stdin>,在< module>中的第2行。
ZeroDivisionError:被零除
上面的异常是以下异常的直接原因:
追溯(最近一次调用为最新):
文件< module>中第4行的< stdin>
AssertionError:除以零
There is a new feature that was introduced in python3 - exception chaining. For some reasons I need to disable it for certain exceptions in my code.
Here is sample code:
try:
print(10/0)
except ZeroDivisionError as e:
sys.exc_info()
raise AssertionError(str(e))
what I see:
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
what I want to see:
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
I tried to use sys.exc_clear()
, but this mehtod is removed from python 3 too.
I can use workaround that works
exc = None
try:
print(10/0)
except ZeroDivisionError as e:
exc = e
if exc:
raise AssertionError(str(exc))
but I believe that there is better solution.
解决方案 Simple Answer
try:
print(10/0)
except ZeroDivisionError as e:
raise AssertionError(str(e)) from None
However, you probably actually want:
try:
print(10/0)
except ZeroDivisionError as e:
raise AssertionError(str(e)) from e
Explanation
__cause__
Implicit exception chaining happens through __context__
when there isn't an explicit cause exception set.
Explicit exception chaining works through __cause__
so if you set __cause__
to the exception itself, it should stop the chaining. If __cause__
is set, Python will suppress the implicit message.
try:
print(10/0)
except ZeroDivisionError as e:
exc = AssertionError(str(e))
exc.__cause__ = exc
raise exc
raise from
We can use "raise from" to do the same thing:
try:
print(10/0)
except ZeroDivisionError as e:
exc = AssertionError(str(e))
raise exc from exc
None __cause__
Setting __cause__
to None
actually does the same thing:
try:
print(10/0)
except ZeroDivisionError as e:
exc = AssertionError(str(e))
exc.__cause__ = None
raise exc
raise from None
So that brings us to the most elegant way to do this which is to raise from None
:
try:
print(10/0)
except ZeroDivisionError as e:
raise AssertionError(str(e)) from None
But I would argue that you usually want to explicitly raise your exception from the cause exception so the traceback is preserved:
try:
print(10/0)
except ZeroDivisionError as e:
raise AssertionError(str(e)) from e
This will give us a slightly different message that states that the first exception was the direct cause of the second:
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
这篇关于在python 3中禁用异常链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!