Search code examples
pythonpython-3.xerror-handlingpython-decoratorstraceback

Python display custom error message / traceback on every exception


Does Python support a way to display the same custom error message for every exception / raise / assert (no matter where the code broke)?

My current crack at it uses a decorator. I have a function main and it displays the traceback fine, but I want it to also print my_var (which is INSIDE the function scope) every time ANY error is thrown. So obviously there is a scope problem with this - it's just to illustrate what I want to do. Any ideas are appreciated.

import traceback

def exit_with_traceback(func, *args, **kwargs):
    def wrap(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except:
            # how do I get this to print my_var AND the traceback?
            print(traceback.format_exc())
    return wrap
        
@exit_with_traceback
def main(bar=1):
    my_var = 'hello world'  # variable specific to main()
    return bar + 1

main(bar=None)  # run main() to throw the exception

Solution

  • You can try to override the excepthook function in sys module. From its documentation:

    When an exception is raised and uncaught, the interpreter calls sys.excepthook with three arguments, the exception class, exception instance, and a traceback object.

    So the code may look something like this (I've used your example):

    import sys
    
    
    # define custom exception hook
    def custom_exception_hook(exc_type, value, traceback):
        print('Custom exception hook')
        print('Type:', exc_type)
        print('Value:', value)
        print('Traceback:', traceback)
        lc = traceback.tb_next.tb_frame.f_locals
        print(lc.get('my_var'))  # this prints "hello world"
    
    
    # override the default exception hook
    sys.excepthook = custom_exception_hook
    
    
    def main(bar=1):
        my_var = 'hello world'  # variable specific to main()
        return bar + 1
    
    
    main(bar=None)  # run main() to throw the exception
    

    The overriding of sys.excepthook won't work from IDLE, but it works just fine from command line. Hope this will be helpful.