pythonexceptionwrapperpython-decorators

Python exception stack trace not full when function is wrapped


I have two files t.py:

import functools
import traceback


def wrapper(func):
    @functools.wraps(func)
    def wrapped(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            traceback.print_exception(e)

    return wrapped


@wrapper
def problematic_function():
    raise ValueError("Something went wrong")

and t2.py:

from t import problematic_function

problematic_function()

when I call from command line python t2.py, the stack trace information that has info from t2.py is lost when printing traceback.print_exception(e) in the t.py. What I get is

Traceback (most recent call last):
  File "/home/c/t.py", line 9, in wrapped
    return func(*args, **kwargs)
  File "/home/c/t.py", line 18, in problematic_function
    raise ValueError("Something went wrong")
ValueError: Something went wrong

where as if I remove the decorator I get:

Traceback (most recent call last):
  File "/home/c/t2.py", line 3, in <module>
    problematic_function()
  File "/home/cu/t.py", line 17, in problematic_function
    raise ValueError("Something went wrong")
ValueError: Something went wrong

How do I get the full stack trace in the wrapped function as without the wrapper? Thanks!


Solution

  • To print the full stack trace you can unpack traceback.walk_tb to obtain the last frame of the stack from the traceback, and pass it to traceback.print_stack as a starting frame to output the entire stack:

    def wrapper(func):
        @functools.wraps(func)
        def wrapped(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                *_, (last_frame, _) = traceback.walk_tb(e.__traceback__)
                traceback.print_stack(last_frame)
    
        return wrapped
    

    Demo here