CPython Traceback: tb_frame, tb_lasti, and tb_lineno

When an exception occurs in CPython, the runtime creates a traceback object that encapsulates execution context at each level of the unwinding call stack. This article provides a focused explanation of the core metadata maintained by CPython traceback objects through three primary attributes: tb_frame, tb_lasti, and tb_lineno. Understanding these attributes reveals how Python connects low-level bytecode execution to human-readable source code during post-mortem debugging and exception handling.

The Traceback Object Architecture

Traceback objects are represented internally by the PyTracebackObject struct in CPython. Instances form a singly linked list via the tb_next attribute, representing the sequence of stack frames traversed from the point where the exception was raised to the point where it is caught. At each node in this chain, tb_frame, tb_lasti, and tb_lineno capture the exact execution state of that specific frame.

tb_frame: The Execution Frame Context

The tb_frame attribute holds a reference to a frame object (types.FrameType). A frame represents the execution environment of a specific function call, module, or class definition.

Through tb_frame, the traceback maintains access to the full lexical and runtime environment:

Because tb_frame retains references to local variables, keeping traceback objects alive can unintentionally extend the lifecycle of objects in local scope, preventing garbage collection until the traceback is cleared.

tb_lasti: The Bytecode Instruction Pointer

The tb_lasti (last instruction) attribute stores an integer representing the index offset of the last bytecode instruction evaluated inside the frame's code object.

Key details maintained by tb_lasti include:

tb_lineno: The Source Code Line Number

The tb_lineno attribute is an integer recording the line number in the source file corresponding to the active execution state.

Its responsibilities include:

Together, tb_frame, tb_lasti, and tb_lineno bridge CPython's execution layers: tb_lasti provides virtual machine precision, tb_frame preserves the runtime memory state, and tb_lineno maps the failure back to the original Python source code.