How to Get Exception Information (Type, File, Line Number) in Python
When an exception occurs in Python, it's often crucial to get detailed information about it: the exception type, the file where it occurred, and the line number.
This guide explains how to retrieve this information using:
- Attributes of the exception object itself.
- The
sys.exc_info()function. - The
tracebackmodule.
We'll cover single exceptions and how to handle multiple exceptions in a traceback.
Getting Exception Information from the Exception Object
The exception object itself (the e in except Exception as e:) contains valuable information:
try:
raise ValueError('invalid value')
except ValueError as e: # Catch the exception
e_type = type(e).__name__ # Get the exception type (e.g., 'ValueError')
e_file = e.__traceback__.tb_frame.f_code.co_filename # Get the filename
e_line = e.__traceback__.tb_lineno # Get the line number
e_message = str(e) # Get the exception message
print(f'exception type: {e_type}') # Output: exception type: ValueError
print(f'exception filename: {e_file}') # Output: exception filename: /path/to/your/file.py
print(f'exception line number: {e_line}') # Output: exception line number: 2
print(f'exception message: {e_message}') # Output: exception message: invalid value
type(e).__name__: Gets the name of the exception class (e.g., "ValueError", "TypeError"). This is generally more reliable than usinge.__class__.__name__directly.e.__traceback__: This is the traceback object associated with the exception. Traceback objects contain the call stack information.e.__traceback__.tb_frame.f_code.co_filename: This drills down into the traceback to get the filename.tb_frameis the current stack frame,f_codeis the code object, andco_filenameis the filename.e.__traceback__.tb_lineno: This gets the line number within the file where the exception occurred.str(e): This gets the exception's message (the string argument you passed toraise ValueError(...)).
Getting Exception Information with sys.exc_info()
The sys.exc_info() function returns a tuple containing information about the currently handled exception:
import sys
import os
try:
raise ValueError('invalid value')
except ValueError as e:
e_type, e_object, e_traceback = sys.exc_info() # Get exception info
e_filename = os.path.split(e_traceback.tb_frame.f_code.co_filename)[1] # Extract filename
e_message = str(e)
e_line_number = e_traceback.tb_lineno
print(f'exception type: {e_type}') # Output: exception type: <class 'ValueError'>
print(f'exception filename: {e_filename}') # Output: exception filename: main.py
print(f'exception line number: {e_line_number}') # Output: exception line number: 5
print(f'exception message: {e_message}') # Output: exception message: invalid value
- The method returns a tuple containing exception type, exception object, and exception traceback.
sys.exc_info() returns information about the currently handled exception.
If no exception is being handled, it returns (None, None, None). Therefore, you must use it inside an except block.
Getting Formatted Exception Information with traceback
The traceback module provides functions for working with tracebacks in a more structured way.
Using traceback.format_exc()
traceback.format_exc() returns a formatted string representing the entire traceback, similar to what you see when an unhandled exception occurs:
import traceback
try:
raise ValueError('invalid value')
except ValueError as e:
print(traceback.format_exc())
Output:
Traceback (most recent call last):
File "/path/to/your/file.py", line 4, in <module>
raise ValueError('invalid value')
ValueError: invalid value
Using traceback.print_exc()
traceback.print_exc() prints the formatted traceback directly to the console (or to a file if you specify one):
import traceback
try:
raise ValueError('invalid value')
except ValueError as e:
traceback.print_exc()
Output (to console):
Traceback (most recent call last):
File "/path/to/your/file.py", line 4, in <module>
raise ValueError('invalid value')
ValueError: invalid value
Handling Multiple Exceptions in a Traceback
If you have nested exceptions (an exception raised while handling another exception), you can iterate through the traceback to get information about each exception in the chain:
import sys
import os
try:
raise ValueError('invalid value')
except ValueError as e:
all_exceptions = []
tback = e.__traceback__
while tback is not None: # Iterate over the traceback frames
e_type = type(e).__name__
e_file = tback.tb_frame.f_code.co_filename
e_line = tback.tb_lineno
e_message = str(e)
all_exceptions.append({
'e_type': e_type,
'e_file': e_file,
'e_line': e_line,
'e_message': e_message,
})
tback = tback.tb_next # Move to the *next* frame in the traceback
print(all_exceptions)
Output:
[
{'e_type': 'ValueError',
'e_file': '/path/to/your/file.py',
'e_line': 3, 'e_message': 'invalid value'
}
]
- The
tb_nextattribute is used to access the next frame in the traceback, creating a linked structure to iterate over.
This example shows the basic idea. In real code, you'd likely use traceback.extract_tb or traceback.format_exception to get more structured information and handle complex exception chains properly. This example is simplified for illustrative purposes.