As of Python 3.0, raising an exception in the except
block will automatically add the captured exception to the __context__
attribute of the new exception. This will result in a printout of both exceptions.
Essentially, this is the way the current exception will carry information about the previous exception. For example:
try:
raise ValueError('ValueError')
except ValueError:
raise TypeError('TypeError')
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: ValueError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
TypeError: TypeError
You can also add __cause__
to any exception using the expression raise ... from
. In the example below, you can see that the message has changed:
try:
raise ValueError('ValueError')
except ValueError as ve:
raise TypeError('TypeError') from ve
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: ValueError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
TypeError: TypeError
More complex examples with printouts of all the private variables we have talked about so far to better understand the difference:
try:
try:
raise ValueError("ValueError")
except ValueError as first:
raise TypeError("TypeError")
except TypeError as second:
print("The exception was", repr(second))
print("Its __context__ was", repr(second.__context__))
print("Its __cause__ was", repr(second.__cause__))
The exception was TypeError('TypeError',)
Its __context__ was ValueError('ValueError',)
Its __cause__ was None
try:
try:
raise ValueError("ValueError")
except ValueError as first:
raise TypeError("TypeError") from first
except TypeError as second:
print("The exception was", repr(second))
print("Its __context__ was", repr(second.__context__))
print("Its __cause__ was", repr(second.__cause__))
The exception was TypeError('TypeError',)
Its __context__ was ValueError('ValueError',)
Its __cause__ was ValueError('ValueError',)