The traceback module formats and extracts exception information. Essential for logging, error reporting, and debugging tools.

Get Traceback as String

import traceback
 
try:
    1 / 0
except:
    # Get traceback as string
    tb_str = traceback.format_exc()
    print(tb_str)
 
# Output:
# Traceback (most recent call last):
#   File "example.py", line 4, in <module>
#     1 / 0
# ZeroDivisionError: division by zero
import traceback
 
try:
    raise ValueError("Something went wrong")
except:
    traceback.print_exc()  # Prints to stderr
import traceback
import sys
 
try:
    raise RuntimeError("Error!")
except:
    # Print to file
    with open("error.log", "a") as f:
        traceback.print_exc(file=f)
    
    # Print to stdout instead of stderr
    traceback.print_exc(file=sys.stdout)

Extract Stack Frames

import traceback
import sys
 
try:
    def inner():
        raise ValueError("Bad value")
    
    def outer():
        inner()
    
    outer()
except:
    exc_type, exc_value, exc_tb = sys.exc_info()
    
    # Extract as list of FrameSummary objects
    frames = traceback.extract_tb(exc_tb)
    
    for frame in frames:
        print(f"{frame.filename}:{frame.lineno} in {frame.name}")
        print(f"  {frame.line}")

Format Individual Parts

import traceback
import sys
 
try:
    raise KeyError("missing")
except:
    exc_type, exc_value, exc_tb = sys.exc_info()
    
    # Format just the traceback
    tb_lines = traceback.format_tb(exc_tb)
    print("Traceback:")
    print("".join(tb_lines))
    
    # Format just the exception
    exc_lines = traceback.format_exception_only(exc_type, exc_value)
    print("Exception:")
    print("".join(exc_lines))

TracebackException (Modern API)

Python 3.5+ provides a cleaner object-oriented interface:

import traceback
 
try:
    def broken():
        return 1 / 0
    broken()
except Exception as e:
    te = traceback.TracebackException.from_exception(e)
    
    # Format as lines
    for line in te.format():
        print(line, end="")
    
    # Access parts
    print(f"Exception type: {te.exc_type.__name__}")
    print(f"Exception message: {te._str}")

Limit Traceback Depth

import traceback
 
try:
    # Deep recursion
    def recurse(n):
        if n == 0:
            raise ValueError("Bottom")
        recurse(n - 1)
    recurse(100)
except:
    # Show only last 3 frames
    traceback.print_exc(limit=3)
    
    # Or as string
    tb_str = traceback.format_exc(limit=3)

Current Stack (No Exception)

import traceback
 
def show_stack():
    # Print current stack trace
    traceback.print_stack()
    
    # Get as string
    stack_str = "".join(traceback.format_stack())
    return stack_str
 
def caller():
    show_stack()
 
caller()

Practical Examples

Logging Exceptions

import traceback
import logging
 
logging.basicConfig(level=logging.ERROR)
logger = logging.getLogger(__name__)
 
def process_data(data):
    try:
        return data["key"]["nested"]
    except Exception:
        logger.error("Failed to process data:\n%s", traceback.format_exc())
        return None

Custom Error Handler

import traceback
import sys
from datetime import datetime
 
def error_handler(exc_type, exc_value, exc_tb):
    """Custom exception handler with logging."""
    timestamp = datetime.now().isoformat()
    
    with open("errors.log", "a") as f:
        f.write(f"\n{'='*60}\n")
        f.write(f"Timestamp: {timestamp}\n")
        f.write(f"Exception: {exc_type.__name__}: {exc_value}\n")
        f.write("Traceback:\n")
        traceback.print_tb(exc_tb, file=f)
    
    # Still print to stderr
    sys.__excepthook__(exc_type, exc_value, exc_tb)
 
sys.excepthook = error_handler

Exception Serialization

import traceback
import json
 
def serialize_exception(e: Exception) -> dict:
    """Convert exception to JSON-serializable dict."""
    te = traceback.TracebackException.from_exception(e)
    
    return {
        "type": te.exc_type.__name__,
        "message": str(e),
        "traceback": list(te.format()),
        "frames": [
            {
                "file": frame.filename,
                "line": frame.lineno,
                "function": frame.name,
                "code": frame.line,
            }
            for frame in te.stack
        ],
    }
 
try:
    raise ValueError("Test error")
except Exception as e:
    error_data = serialize_exception(e)
    print(json.dumps(error_data, indent=2))

Chained Exceptions

import traceback
 
try:
    try:
        raise ValueError("Original error")
    except ValueError as e:
        raise RuntimeError("Wrapper error") from e
except RuntimeError as e:
    te = traceback.TracebackException.from_exception(e)
    
    # Shows both exceptions with "caused by" chain
    print("".join(te.format()))

Quick Reference

import traceback
 
# Get traceback as string
traceback.format_exc(limit=None)
 
# Print traceback to stderr
traceback.print_exc(limit=None, file=None)
 
# Extract frames from traceback
traceback.extract_tb(tb, limit=None)
 
# Format traceback only
traceback.format_tb(tb, limit=None)
 
# Format exception only
traceback.format_exception_only(exc_type, exc_value)
 
# Format complete exception
traceback.format_exception(exc_type, exc_value, exc_tb)
 
# Print current stack
traceback.print_stack(f=None, limit=None, file=None)
 
# Modern API
te = traceback.TracebackException.from_exception(e)
te.format()  # Generator of lines
FunctionReturnsUse Case
format_exc()StringLogging
print_exc()NoneQuick debug
extract_tb()List[FrameSummary]Frame analysis
format_tb()List[str]Custom formatting
TracebackExceptionObjectModern, flexible

traceback gives you control over exception presentation. Use it for better error logs and debugging tools.

React to this post: