Search code examples
pythonexceptiontracebackbacktrace

python: backtrace.hook does not work with backtrace.print_exc()


I can't figure out how to color a backtrace I print myself.
This colors my backtrace:

#!/bin/python3
import backtrace
backtrace.hook()
raise Exception('here')

But if I catch the exception and print it... then no color:

#!/bin/python3
import backtrace
backtrace.hook()
import traceback
try:
    raise Exception('here')
except Exception:
    traceback.print_exc()

I know these are 2 different packages, but they should be able to work together.
How do I catch and print exceptions (and a stack trace) in color?


Solution

  • backtrace internally uses sys.excepthook do the trick. When an exception is raised and uncaught, the interpreter calls sys.excepthook with three arguments, the exception class, exception instance, and a traceback object. In your first case, when you call backtrace.hook(), the backtrace library essentially set the sys.excepthook to a custom function which can do all sorts of magic with the exception instance(coloring etc....)

    >>> def custom_hook(*args):
    ...     print(args)
    ...
    >>>
    >>> import sys
    >>> sys.excepthook = custom_hook
    >>>
    >>> 1 / 0 # No exception raised, instead it calls `custom_hook`
    (<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero'), <traceback object at 0x000001FA502B98C0>)
    

    The excepthook does not call if the exception is raised and caught(using except).

    >>> def custom_hook(*args):
    ...     print(args)
    ...
    >>>
    >>> import sys
    >>> sys.excepthook = custom_hook
    >>>
    >>> try:
    ...     1 / 0 
    ... except: # Since the exception is caught here, it won't call `custom_hook`
    ...     pass
    ...
    

    The exact scenario happened in your case. You have to re-raise the exception once it's caught to get the excepted behavior.