Python如何在抛出错误时省略函数内部的调用栈路径信息
I have a test function that raises an error when given a non-integer input:
def stringtester(integer): if type(integer) != int: raise ValueError("this is not an integer and I only like integers!") else: print("this is an integer and I like integers!") stringtester("this is a string")
When I run this, I get the full traceback including the line where the exception is raised inside the function:
Traceback (most recent call last):
File "C:/Users/user/Python/test.py", line 7, in
stringtester("this is a string")
File "C:/Users/user/Python/test.py", line 3, in stringtester
raise ValueError("this is not a integer and I only like integers!")
ValueError: this is not a integers and I only like integers!
But the root issue is the incorrect input passed to the function, not the raise line itself. I want to modify the traceback output to only keep the line where the function was called, removing the internal raise line. The desired output is:
Traceback (most recent call last):
File "C:/Users/user/Python/test.py", line 7, in
stringtester("this is a string")
ValueError: this is not an integer and I only like integers!
Is there a way to achieve this?
Answer
Absolutely! You can customize Python's traceback output by overriding the default exception handler using sys.excepthook. This lets you filter and reformat the traceback frames exactly how you want.
Here's a solution tailored to your needs:
import sys import traceback def custom_excepthook(exc_type, exc_value, exc_traceback): # Extract all traceback frames into a readable list tb_frames = traceback.extract_tb(exc_traceback) # Filter out the frame where the exception was raised inside `stringtester` # For your case, this is the last frame in the list filtered_frames = tb_frames[:-1] # Print the standard traceback header print("Traceback (most recent call last):") # Loop through and print each filtered frame with its details for frame in filtered_frames: print(f" File \"{frame.filename}\", line {frame.lineno}, in {frame.name}") print(f" {frame.line}") # Print the final exception type and message print(f"{exc_type.__name__}: {exc_value}") # Replace Python's default exception handler with our custom one sys.excepthook = custom_excepthook def stringtester(integer): if type(integer) != int: raise ValueError("this is not an integer and I only like integers!") else: print("this is an integer and I like integers!") stringtester("this is a string")
How This Works:
sys.excepthookis Python's built-in function for handling uncaught exceptions. By replacing it, we take full control of how tracebacks are displayed.traceback.extract_tb()converts the raw traceback object into a list of frame objects, each containing filename, line number, function name, and the code line itself.- We slice off the last frame (which corresponds to the
raiseline insidestringtester) to get the simplified traceback you want. - Finally, we reprint the filtered frames and exception details in the exact format you requested.
For a More Flexible Solution:
If you want to only filter frames from specific functions (instead of always removing the last frame), you can add a targeted check:
filtered_frames = [ frame for frame in tb_frames if not (frame.name == "stringtester" and "raise" in frame.line.strip()) ]
This ensures we only remove the raise line from your stringtester function, leaving other traceback frames intact for any other exceptions in your code.
内容的提问来源于stack exchange,提问作者SpaceBroetchen

