Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
Open
Labels
Description
Problem
When a method with@_preprocess_data
raises an exception the decorator shows up in the call stack:
ValueError Traceback (most recent call last)Cell In[7], line 6 4 fig, ax = plt.subplots() 5 data = [10, 20, float('nan'), 40]----> 6 ax.pie(data, labels=["A", "B", "C", "D"]) 7 plt.show()File ~\AppData\Local\miniforge3\envs\jupyter\Lib\site-packages\matplotlib\__init__.py:1473, in _preprocess_data.<locals>.inner(ax, data, *args, **kwargs) 1470 @functools.wraps(func) 1471 def inner(ax, *args, data=None, **kwargs): 1472 if data is None:-> 1473 return func( 1474 ax, 1475 *map(sanitize_sequence, args), 1476 **{k: sanitize_sequence(v) for k, v in kwargs.items()}) 1478 bound = new_sig.bind(ax, *args, **kwargs) 1479 auto_label = (bound.arguments.get(label_namer) 1480 or bound.kwargs.get(label_namer))File ~\AppData\Local\miniforge3\envs\jupyter\Lib\site-packages\matplotlib\axes\_axes.py:3334, in Axes.pie(self, x, explode, labels, colors, autopct, pctdistance, shadow, labeldistance, startangle, radius, counterclock, wedgeprops, textprops, center, frame, rotatelabels, normalize, hatch) 3331 x += expl * math.cos(thetam) 3332 y += expl * math.sin(thetam)-> 3334 w = mpatches.Wedge((x, y), radius, 360. * min(theta1, theta2), 3335 360. * max(theta1, theta2), 3336 facecolor=get_next_color(), 3337 hatch=next(hatch_cycle), 3338 clip_on=False, 3339 label=label) 3340 w.set(**wedgeprops) 3341 slices.append(w)
This is rather distracting and makes the stacktrace harder to read.
Proposed solution
We could filter the decorator out of the stacktrace like this
def hidden_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: # Modify the traceback to remove the wrapper from the stack trace tb = traceback.extract_tb(sys.exc_info()[2]) # Filter out the wrapper's frame filtered_tb = [frame for frame in tb if frame.name != wrapper.__name__] # Raise the exception with the modified traceback raise e.with_traceback(traceback.extract_stack(filtered_tb)) return wrapper
Is this a reasonable idea? On the one hand, it's removing irrelevant information (the decorator is an implemenation detail that should not bother the user or anybody debugging internal errors. On the other hand, a stack trace is a technical detail and it may be better to tell the full story there.