inspect
The inspect module provides functions for getting information about live objects in Python. You can examine modules, classes, functions, tracebacks, frames, and code objects at runtime. It’s essential for debugging, building IDEs, and implementing tools that need to understand code structure.
Inspecting Functions and Callables
inspect.signature()
Returns the signature of a callable, showing all parameters with their defaults.
inspect.signature(callable, *, follow_wrapped=True)
| Parameter | Type | Default | Description |
|---|---|---|---|
callable | callable | — | The function or method to inspect |
follow_wrapped | bool | True | Follow the __wrapped__ attribute to original function |
import inspect
def greet(name, greeting="Hello", punctuation="!"):
return f"{greeting}, {name}{punctuation}"
sig = inspect.signature(greet)
print(sig)
# Output: (name, greeting='Hello', punctuation='!')
# Iterate over parameters
for param_name, param in sig.parameters.items():
print(f"{param_name}: default={param.default}, kind={param.kind.name}")
# Output:
# name: default=inspect.Parameter.empty, kind=POSITIONAL_OR_KEYWORD
# greeting: default=Hello, kind=POSITIONAL_OR_KEYWORD
# punctuation: default=!, kind=POSITIONAL_OR_KEYWORD
inspect.getmembers()
Returns all members of an object that match a given predicate.
inspect.getmembers(object, predicate=None)
| Parameter | Type | Default | Description |
|---|---|---|---|
object | object | — | The object to inspect |
predicate | callable | None | Optional filter function(member_name, member_value) -> bool |
import inspect
class MyClass:
class_attr = 42
def __init__(self):
self.instance_attr = "hello"
def method(self):
pass
# Get all members
for name, value in inspect.getmembers(MyClass):
print(f"{name}: {type(value).__name__}")
# Output shows all attributes including __init__, __class__, etc.
# Filter to only methods
methods = inspect.getmembers(MyClass, inspect.isfunction)
print([m[0] for m in methods])
# Output: ['__init__', 'method']
Getting Source Code
inspect.getsource()
Returns the source code of a function, class, or method as a string.
inspect.getsource(object)
import inspect
def example_function(x, y):
"""This is a docstring."""
result = x + y
return result
print(inspect.getsource(example_function))
# Output:
# def example_function(x, y):
# """This is a docstring."""
# result = x + y
# return result
inspect.getfile()
Returns the name of the Python file where an object is defined.
inspect.getfile(object)
import inspect
import os
print(inspect.getfile(inspect.signature))
# Output: /usr/lib/python3.11/inspect.py
print(inspect.getfile(os))
# Output: <frozen os> (built-in module)
# Works with custom classes
class MyClass:
pass
print(inspect.getfile(MyClass))
# Output: /path/to/current/file.py
Frame and Stack Inspection
inspect.currentframe()
Returns the current frame object. Frames contain execution context.
inspect.currentframe() -> FrameType
import inspect
def caller():
frame = inspect.currentframe()
print(f"Called from: {frame.f_code.co_filename}")
print(f"Line number: {frame.f_lineno}")
print(f"Function name: {frame.f_code.co_name}")
# Access local variables
print(f"Local variables: {frame.f_locals}")
return frame
def wrapper():
x = 42
y = "test"
caller()
wrapper()
inspect.stack()
Returns a list of FrameInfo namedtuples representing the call stack.
inspect.stack(context=1) -> list[FrameInfo]
| Parameter | Type | Default | Description |
|---|---|---|---|
context | int | 1 | Number of lines of source code to include before/after |
import inspect
def function_c():
for frame_info in inspect.stack():
print(f"{frame_info.function} at {frame_info.filename}:{frame_info.lineno}")
def function_b():
function_c()
def function_a():
function_b()
function_a()
# Output:
# function_c at /path/to/file.py:15
# function_b at /path/to/file.py:19
# function_a at /path/to/file.py:23
# <module> at /path/to/file.py:26
Other Useful Functions
inspect.getdoc()
Gets the docstring of an object, cleaned up.
import inspect
def documented():
"""
This is a multi-line
docstring.
"""
pass
print(inspect.getdoc(documented))
# Output: This is a multi-line\n docstring.
inspect.getmodulename()
Extracts the module name from a filename.
print(inspect.getmodulename("/path/to/mymodule.py"))
# Output: mymodule
print(inspect.getmodulename("/path/to/mymodule"))
# Output: mymodule
inspect.ismodule(), inspect.isclass(), inspect.isfunction(), inspect.ismethod()
Type-checking predicates for introspection.
import inspect
import os
print(inspect.ismodule(os)) # True
print(inspect.isclass(os)) # False
print(inspect.isfunction(inspect.stack)) # True
print(inspect.ismethod(os.path.join)) # True
Practical Example: Building a Simple Debugger
import inspect
def debug_call(frame, event, arg):
if event == 'call':
code = frame.f_code
args = inspect.signature(code.co_varnames[:code.co_argcount])
print(f"Calling {code.co_name}({', '.join(args)}) at line {frame.f_lineno}")
return debug_call
# Enable tracing
# sys.settrace(debug_call)