How Python Inspect Module Introspects Objects

Python's built-in inspect module provides a comprehensive suite of tools to examine live objects, classes, functions, and active execution frames at runtime. By tapping directly into the CPython runtime's internal data structures, type systems, and evaluation stack, it translates raw interpreter state into human-readable, programmatic metadata. This article explores how inspect works under the hood to extract object attributes, trace class hierarchies, inspect execution frames, and retrieve original source code.

Inspecting Live Objects and Types

At its core, Python treats everything as an object, backed by a C-level structure (like PyObject) containing a reference count, a type pointer (ob_type), and often an internal dictionary (__dict__). The inspect module leverages these native hooks:

Class Inspection and Method Resolution

When analyzing classes, inspect inspects the structure of Python's inheritance system:

Execution Frames and Call Stack Introspection

Python executes code within a stack of frame objects (PyFrameObject), which represent the execution context of functions or modules. The inspect module accesses this stack through low-level hooks like sys._getframe():

Source Code Retrieval and Line Caching

One of inspect's most powerful capabilities is retrieving the original source code of live objects:

  1. Locating the File: The module retrieves the co_filename and co_firstlineno fields from a callable's __code__ attribute or searches a class's module namespace (__module__).
  2. Reading the Code: It uses Python's internal linecache module to read the source file from disk into memory, preventing redundant I/O operations.
  3. Tokenizing and Parsing: To locate where a multi-line function or class ends, inspect.getsource() uses the tokenize module to tokenize the Python code starting from co_firstlineno. It tracks indentation levels and statement boundaries, ensuring that only the relevant block of code is returned.