简体   繁体   中英

How to access re-raised exception in Python 3?

In Python 3, there's a useful raise ... from ... feature to re-raise an exception. That said, how do you find the original (/ re-raised) exception from the raised exception? Here's a (silly) example with comments to demonstrate what I mean--

def some_func():
    try:
      None() # TypeError: 'NoneType' object is not callable
    except as err:
      raise Exception("blah") from err

try:
    some_func()
except as err:
    # how can I access the original exception (TypeError)?

It's in the __cause__ attribute of the raised exception. Taken from the docs on the raise statement it says regarding raise ... from ... :

The from clause is used for exception chaining: if given, the second expression must be another exception class or instance, which will then be attached to the raised exception as the __cause__ attribute (which is writable). If the raised exception is not handled, both exceptions will be printed.

So, in your given scenario, repr ing the __cause__ attribute:

def some_func():
    try:
      None() # TypeError: 'NoneType' object is not callable
    except TypeError as err:
      raise Exception("blah") from err

try:
    some_func()
except Exception as er:
    print(repr(er.__cause__))

Will print out:

TypeError("'NoneType' object is not callable",)

Whenever an exception is raised from an exception handler (the except clause), the original exception will bestored in new exception's __context__ .

Whenever an exception is raised using from syntax, the exception specified in from will be saved in the __cause__ attribute of the new exception.

In the usual use case, that amounts to both __cause__ and __context__ containing the original exception:

def f():
    try:
        raise Exception('first exception')
    except Exception as e:
        raise Exception('second exception') from e

try:
    f()
except Exception as e:
    print('This exception', e)
    print('Original exception', e.__context__)
    print('Also original exception', e.__cause__)

Here is also an example of when __context__ is set:

try:
    raise Exception('first exception')
except Exception as e:
    raise Exception('second exception')

and an example of when __cause__ is set:

e = Exception('first exception')
raise Exception('second exception') from e

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM