Question: Python (and ipython) has very powerful post-mortem debugging capabilities, allowing variable inspection and command execution at each scope in the traceback. The up/down debugger commands allow changing frame for the stack trace of the final exception, but what about the __cause__ of that exception, as defined by the raise ... from ... syntax? Python 3.7.6 (default, Jan 8 2020, 13:42:34) Type 'copyright', 'credits' or 'license' for more information IPython 7.11.1 -- An enhanced Interactive Python. Type '?' for help. In [1]: def foo(): ...: bab = 42 ...: raise TypeError ...: In [2]: try: ...: foo() ...: except TypeError as err: ...: barz = 5 ...: raise ValueError from err ...: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-2-dd046d7cece0> in <module> 1 try: ----> 2 foo() 3 except TypeError as err: <ipython-input-1-da9a05838c59> in foo() 2 bab = 42 ----> 3 raise TypeError 4 TypeError: The above exception was the direct cause of the following exception: ValueError Traceback (most recent call last) <ipython-input-2-dd046d7cece0> in <module> 3 except TypeError as err: 4 barz = 5 ----> 5 raise ValueError from err 6 ValueError: In [3]: %debug > <ipython-input-2-dd046d7cece0>(5)<module>() 2 foo() 3 except TypeError as err: 4 barz = 5 ----> 5 raise ValueError from err 6 ipdb> barz 5 ipdb> bab *** NameError: name 'bab' is not defined ipdb> down *** Newest frame ipdb> up *** Oldest frame  Is there a way to access bab from the debugger? EDIT: I realized post-mortem debugging isn't just a feature of ipython and ipdb, it's actually part of vanilla pdb. The above can also be reproduced by putting the code into a script testerr.py and running python -m pdb testerr.py and running continue. After the error, it says Uncaught exception. Entering post mortem debugging Running 'cont' or 'step' will restart the program  and gives a debugger at the same spot.

Answer: You can use the with_traceback(tb) method to preserve the original exception's traceback: try: foo() except TypeError as err: barz = 5 raise ValueError().with_traceback(err.__traceback__) from err  Note that I have updated the code to raise an exception instance rather than the exception class. Here is the full code snippet in iPython: In [1]: def foo(): ...: bab = 42 ...: raise TypeError() ...: In [2]: try: ...: foo() ...: except TypeError as err: ...: barz = 5 ...: raise ValueError().with_traceback(err.__traceback__) from err ...: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-2-a5a6d81e4c1a> in <module> 1 try: ----> 2 foo() 3 except TypeError as err: <ipython-input-1-ca1efd1bee60> in foo() 2 bab = 42 ----> 3 raise TypeError() 4 TypeError: The above exception was the direct cause of the following exception: ValueError Traceback (most recent call last) <ipython-input-2-a5a6d81e4c1a> in <module> 3 except TypeError as err: 4 barz = 5 ----> 5 raise ValueError().with_traceback(err.__traceback__) from err 6 <ipython-input-2-a5a6d81e4c1a> in <module> 1 try: ----> 2 foo() 3 except TypeError as err: 4 barz = 5 5 raise ValueError().with_traceback(err.__traceback__) from err <ipython-input-1-ca1efd1bee60> in foo() 1 def foo(): 2 bab = 42 ----> 3 raise TypeError() 4 ValueError: In [3]: %debug > <ipython-input-1-ca1efd1bee60>(3)foo() 1 def foo(): 2 bab = 42 ----> 3 raise TypeError() 4 ipdb> bab 42 ipdb> u > <ipython-input-2-a5a6d81e4c1a>(2)<module>() 1 try: ----> 2 foo() 3 except TypeError as err: 4 barz = 5 5 raise ValueError().with_traceback(err.__traceback__) from err ipdb> u > <ipython-input-2-a5a6d81e4c1a>(5)<module>() 2 foo() 3 except TypeError as err: 4 barz = 5 ----> 5 raise ValueError().with_traceback(err.__traceback__) from err 6 ipdb> barz 5  EDIT - An alternative inferior approach Addressing @user2357112supportsMonica's first comment, if you wish to avoid multiple dumps of the original exception's traceback in the log, it's possible to raise from None. However, as @user2357112supportsMonica's second comment states, this hides the original exception's message. This is particularly problematic in the common case where you're not post-mortem debugging but rather inspecting a printed traceback. try: foo() except TypeError as err: barz = 5 raise ValueError().with_traceback(err.__traceback__) from None  Here is the code snippet in iPython: In [4]: try: ...: foo() ...: except TypeError as err: ...: barz = 5 ...: raise ValueError().with_traceback(err.__traceback__) from None ...: --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-6-b090fb9c510e> in <module> 3 except TypeError as err: 4 barz = 5 ----> 5 raise ValueError().with_traceback(err.__traceback__) from None 6 <ipython-input-6-b090fb9c510e> in <module> 1 try: ----> 2 foo() 3 except TypeError as err: 4 barz = 5 5 raise ValueError().with_traceback(err.__traceback__) from None <ipython-input-2-ca1efd1bee60> in foo() 1 def foo(): 2 bab = 42 ----> 3 raise TypeError() 4 ValueError: In [5]: %debug > <ipython-input-2-ca1efd1bee60>(3)foo() 1 def foo(): 2 bab = 42 ----> 3 raise TypeError() 4 ipdb> bab 42 ipdb> u > <ipython-input-6-b090fb9c510e>(2)<module>() 1 try: ----> 2 foo() 3 except TypeError as err: 4 barz = 5 5 raise ValueError().with_traceback(err.__traceback__) from None ipdb> u > <ipython-input-6-b090fb9c510e>(5)<module>() 3 except TypeError as err: 4 barz = 5 ----> 5 raise ValueError().with_traceback(err.__traceback__) from None 6 ipdb> barz 5  Raising from None is required since otherwise the chaining would be done implicitly, attaching the original exception as the new exception’s __context__ attribute. Note that this differs from the __cause__ attribute which is set when the chaining is done explicitly. In [6]: try: ...: foo() ...: except TypeError as err: ...: barz = 5 ...: raise ValueError().with_traceback(err.__traceback__) ...: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-5-ee78991171cb> in <module> 1 try: ----> 2 foo() 3 except TypeError as err: <ipython-input-2-ca1efd1bee60> in foo() 2 bab = 42 ----> 3 raise TypeError() 4 TypeError: During handling of the above exception, another exception occurred: ValueError Traceback (most recent call last) <ipython-input-5-ee78991171cb> in <module> 3 except TypeError as err: 4 barz = 5 ----> 5 raise ValueError().with_traceback(err.__traceback__) 6 <ipython-input-5-ee78991171cb> in <module> 1 try: ----> 2 foo() 3 except TypeError as err: 4 barz = 5 5 raise ValueError().with_traceback(err.__traceback__) <ipython-input-2-ca1efd1bee60> in foo() 1 def foo(): 2 bab = 42 ----> 3 raise TypeError() 4 ValueError: