Open
Description
Minimal example:
def test_errors():
ex1 = ValueError("abcd")
ex2 = IndexError("efgh")
ex3 = KeyError("ijkl")
ex4 = RuntimeError("mnop")
ex1.__cause__ = ex2
ex2.__context__ = ex3
ex3.__cause__ = ex4
raise ex1
Which has the following output:
Expand
RuntimeError: mnop
The above exception was the direct cause of the following exception:
RuntimeError: mnop
The above exception was the direct cause of the following exception:
KeyError: 'ijkl'
During handling of the above exception, another exception occurred:
RuntimeError: mnop
The above exception was the direct cause of the following exception:
KeyError: 'ijkl'
During handling of the above exception, another exception occurred:
IndexError: efgh
The above exception was the direct cause of the following exception:
def test_errors():
ex1 = ValueError("abcd")
ex2 = IndexError("efgh")
ex3 = KeyError("ijkl")
ex4 = RuntimeError("mnop")
ex1.__cause__ = ex2
ex2.__context__ = ex3
ex3.__cause__ = ex4
> raise ex1
E ValueError: abcd
test.py:9: ValueError
What's happening is a little clearer when running with colourful output, the first, third and sixth "the above exception" lines are highlighted, but the rest are plain. Seems at each step of the chain, the full traceback for that exception is output, which includes that of any that happened higher in the chain. This only happens if __traceback__
is None
, in practice I found this by messing with it on caught exceptions.
System details
Windows 10
> python --version
Python 3.9.0
> pip list
Package Version
------------ -------
atomicwrites 1.4.0
attrs 20.3.0
colorama 0.4.4
iniconfig 1.1.1
packaging 20.9
pip 21.0.1
pluggy 0.13.1
py 1.10.0
pyparsing 2.4.7
pytest 6.2.2
setuptools 52.0.0
toml 0.10.2
wheel 0.36.2