Photo by Growtika / Unsplash

TIL - Python's sys.settrace is How Python Debuggers and Coverage Tools Work Under the Hood

Today I Learned May 2, 2026

sys.settrace registers a callable that Python calls on every line execution, function call, and exception. It's the hook that powers pdbcoverage.py, and custom profilers.

# demo.py

import sys

def tracer(frame, event, arg):
    """Called for every trace event."""
    filename = frame.f_code.co_filename.split("/")[-1]
    lineno   = frame.f_lineno
    name     = frame.f_code.co_name

    if event == "call":
        print(f"CALL   {name}() in {filename}")
    elif event == "line":
        print(f"LINE   {filename}:{lineno}")
    elif event == "return":
        print(f"RETURN {name}() → {arg!r}")
    elif event == "exception":
        print(f"EXCEPT {arg[0].__name__} in {name}()")

    return tracer   # must return itself to trace nested calls

def add(a, b):
    result = a + b
    return result

sys.settrace(tracer)
add(2, 3)
sys.settrace(None)   # disable tracing
CALL   add() in demo.py
LINE   demo.py:21
LINE   demo.py:22
RETURN add() → 5

The tracer must return itself to continue tracing into called functions — returning None disables tracing for that frame's children. sys.setprofile is the lighter-weight alternative when you only care about call/return events, not every line.

Tags