简体   繁体   中英

Python: How to catch inner exception of exception chain?

Consider the simple example:

def f():
    try:
        raise TypeError
    except TypeError:
        raise ValueError

f()

I want to catch TypeError object when ValueError is thrown after f() execution. Is it possible to do it?

If I execute function f() then python3 print to stderr all raised exceptions of exception chain ( PEP-3134 ) like

Traceback (most recent call last):
  File "...", line 6, in f
    raise TypeError
TypeError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "...", line 11, in <module>
    f()
  File "...", line 8, in f
    raise ValueError
ValueError

So I would get the list of all exceptions of exception chain or check if exception of some type ( TypeError in the above example) exists in exception chain.

Python 3 has a beautiful syntactic enhancement on exceptions handling. Instead of plainly raising ValueError, you should raise it from a caught exception, ie:

try:
    raise TypeError('Something awful has happened')
except TypeError as e:
    raise ValueError('There was a bad value') from e

Notice the difference between the tracebacks. This one uses raise from version:

Traceback (most recent call last):
  File "/home/user/tmp.py", line 2, in <module>
    raise TypeError('Something awful has happened')
TypeError: Something awful has happened

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/user/tmp.py", line 4, in <module>
    raise ValueError('There was a bad value') from e
ValueError: There was a bad value

Though the result may seem similar, in fact it is rather different! raise from saves the context of the original exception and allows one to trace all the exceptions chain back - which is impossible with simple raise .

To get the original exception, you simply have to refer to new exception's __context__ attribute, ie

try:
    try:
        raise TypeError('Something awful has happened')
    except TypeError as e:
        raise ValueError('There was a bad value') from e
except ValueError as e:
    print(e.__context__)
>>> Something awful has happened

Hopefully that is the solution you were looking for.

For more details, see PEP 3134 -- Exception Chaining and Embedded Tracebacks

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