PyCodeObject & PyFrameObject Memory Layout
1Concept
When a Python function is executed, CPython creates a `PyFrameObject` holding local variables (`f_localsplus`), value stack (`f_valuestack`), and execution pointer (`f_lasti`) pointing into the read-only `PyCodeObject` (`co_code`).
2Architecture Diagram
[ PyCodeObject (Read-only immutable bytecode) ]
^
| Referenced by
[ PyFrameObject (Dynamic call frame created per invocation) ]
+-------------------------------------------------------+
| f_back (Pointer to parent caller frame) |
| f_localsplus (Fast local variable array) |
| f_valuestack (Evaluation operand stack) |
+-------------------------------------------------------+3Code Example
Python 3.12
import inspect
def inner_function():
frame = inspect.currentframe()
print("=== Execution Call Frame Diagnostics ===")
print(f"Current Function: {frame.f_code.co_name}")
print(f"Caller Function: {frame.f_back.f_code.co_name}")
print(f"Local Variables: {frame.f_locals}")
def outer_function():
user = "Senior Engineer"
inner_function()
outer_function()4Expected Output
=== Execution Call Frame Diagnostics ===
Current Function: inner_function
Caller Function: outer_function
Local Variables: {}5Key Takeaways
- ✓PyCodeObject contains bytecode instructions and is cached in memory.
- ✓PyFrameObject represents active function execution and is destroyed when function returns.
- ✓Recursion limit in Python prevents stack frame exhaustion (`sys.getrecursionlimit()`).