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
traceback
module.
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_frame
is the current stack frame,f_code
is the code object, andco_filename
is 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_next
attribute 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.