在python 3中禁用异常链接

时间:2015-11-19 16:53:57

标签: python python-3.x exception-handling

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(),但是这个mehtod也从python 3中删除了。 我可以使用有效的解决方法

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

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

2 个答案:

答案 0 :(得分:19)

简单回答

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

加注

我们可以使用&#34;来自&#34;做同样的事情:

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

答案 1 :(得分:0)

我们也可以使用 logging,虽然不是 OP 想要的。

import logging
import sys 

try:
    print(10/0)
except ZeroDivisionError as e:
    sys.exc_info()
    logging.error(e)

给予

ERROR:root:division by zero

[Program finished]