【问题标题】:Disable exception chaining in python 3在 python 3 中禁用异常链接
【发布时间】:2016-02-21 22:45:14
【问题描述】:

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))

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

【问题讨论】:

    标签: python python-3.x exception


    【解决方案1】:

    简单回答

    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
    

    【讨论】:

      猜你喜欢
      • 2013-05-01
      • 1970-01-01
      • 2019-04-09
      • 1970-01-01
      • 1970-01-01
      • 2017-06-09
      • 1970-01-01
      • 2011-09-10
      相关资源
      最近更新 更多