Disable exception chaining in python 3

后端 未结 1 951
北荒
北荒 2020-12-16 12:32

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 co

相关标签:
1条回答
  • 2020-12-16 12:54

    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
    
    0 讨论(0)
提交回复
热议问题