__context__ vs __cause__ attributes in exception handling

__context__ vs __cause__ attributes in exception handling

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

Buy me a coffee