0

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

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

This is close to what I had in mind, but doesn't print out the value of my_var which I want in the exception.
What about looking up local variables in the traceback? For example something like this (I tried specific for the example code): "traceback.tb_next.tb_frame.f_locals"
This is a workable approach. I've edited your solution and accepted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.