在python 3中禁用异常链接 [英] Disable exception chaining in python 3

查看:181
本文介绍了在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 __ ,因此,如果将 __ 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:
从无


但是我认为您通常想从原因异常中显式引发异常,以便保留回溯:

 尝试:
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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆