Python: show a nicer stacktrace from your exception

Normally when there’s an exception in your Python code, you’ll be pleasantly shown a very detailed and long stacktrace full of information, sometimes useful or sometimes not. This stacktrace can be very noisy and it will take a while to look through all the code to pinpoint the issue. It’s a lot more useful to see the last line in your application code where the issue occurs. Also, there are cases that you need to capture an inner exception and somehow keep the relevant information for later debugging. This is when a more succint, relevant stacktrace is much needed.

This is also useful when you need to serialize the exception since Python doesn’t support serialization of Exceptions so you’ll have to resort to do a string conversion str(e).

The solution is to the traceback module and some very vaguely documented code to help you go down the stack to get to the right information.

import traceback
import os
def exception_message_with_line_number(e):
    stack_level = 1  # we start at the last line of the exception
    stack = None
    cwd = os.getcwd()
    # traverse the stack to grab the first application code that throw an exception
    while stack_level < 1000:
        stack = traceback.extract_tb(e.__traceback__, -stack_level)[0]
        if not stack.filename.startswith(cwd):
            stack_level += 1
        else:
            break
    filename, lineno, line = stack.filename, stack.lineno, stack.line
    return (
        type(e).__name__ + "::" + str(e) + "@" +
        filename + ":" + str(lineno) + "  `" + line + "`"
    )
try:
    raise Exception("give me my stack")
except Exception as e:
    print(exception_message_with_line_number(e))

Running the above will produce:

Exception::give me my stack@/path/to/your/script.py:25  `raise Exception("give me my stack")`

Happy hacking!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.