Saturday, October 23, 2021

Forgot to set up a custom exception hook? Perhaps it is not too late.

There are many custom exception hook that seek to improve upon the standard one from Python. The very first one is Python's cgitb module, but there are many others including, in no particular order, better_exchookinfi.traceback, the traceback submodule of Rich, the different but similarly named rich-traceback, IPython's ultratb module, better-exceptions, stackprinter, pretty-errors, tbvaccine, stack_data, and likely many more others, including my own friendly/friendly-traceback.

To use any of them, they have to be either installed as a custom sys.excepthook before an exception occurred or explicitly written in an except block to process the information.  They normally get the relevant information from sys.exc_info().

What happens if we try to access this information after a normal traceback has be printed?

Too late: no information is available.

At least, that's what I thought until very recently.  Let's see what we can do using the same problematic code in IPython (just to be different) and using friendly after the fact.

As it turns out, the individual content of the tuple obtained from sys.exc_info() before a traceback is printed are available as individual items: sys.last_type, sys.last_value, and sys.last_traceback. As explaine in sys:

These three variables are not always defined; they are set when an exception is not handled and the interpreter prints an error message and a stack traceback. 


The meaning of the variables is the same as that of the return values from exc_info() above.

Friendly now uses this knowledge: when friendly is imported, it now checks to see if an exception has occurred previously resulting in a printed traceback. If so, it attempts to make use of the information available to help users. This has now been tested with IPython, Jupyter, Colab, Mu, etc. It also works with recent versions of IDLE [1] and the normal CPython interpreter [2].

I have not checked ... but I'd be curious to hear if any other "traceback enhancer" can be used in this way. If you know of any, please let me know.

[1] Excluding SyntaxErrors for now; see this bug report.

[2] With limited success since the information about the code entered is temporarily saved in a file named "<stdin>" whose content can never be retrieved.