inspect — Inspect Live Objects

Purpose:The inspect module provides functions for introspecting on live objects and their source code.

The inspect module provides functions for learning about live objects, including modules, classes, instances, functions, and methods. The functions in this module can be used to retrieve the original source code for a function, look at the arguments to a method on the stack, and extract the sort of information useful for producing library documentation for source code.

Example Module

The rest of the examples for this section use this example file, example.py.

example.py

# This comment appears first
# and spans 2 lines.

# This comment does not show up in the output of getcomments().

"""Sample file to serve as the basis for inspect examples.
"""


def module_level_function(arg1, arg2='default', *args, **kwargs):
    """This function is declared in the module."""
    local_variable = arg1 * 2
    return local_variable


class A(object):
    """The A class."""

    def __init__(self, name):
        self.name = name

    def get_name(self):
        "Returns the name of the instance."
        return self.name

instance_of_a = A('sample_instance')


class B(A):
    """This is the B class.
    It is derived from A.
    """

    # This method is not part of A.
    def do_something(self):
        """Does some work"""

    def get_name(self):
        "Overrides version from A"
        return 'B(' + self.name + ')'

Module Information

The first kind of introspection probes live objects to learn about them. For example, it is possible to discover the classes and functions in a module, the methods of a class, etc.

To determine how the interpreter will treat and load a file as a module, use getmoduleinfo(). Pass a filename as the only argument, and the return value is a tuple including the module base name, the suffix of the file, the mode that will be used for reading the file, and the module type as defined in the imp module. It is important to note that the function looks only at the file’s name, and does not actually check if the file exists or try to read the file.

inspect_getmoduleinfo.py
import imp
import inspect
import sys

if len(sys.argv) >= 2:
    filename = sys.argv[1]
else:
    filename = 'example.py'

try:
    (name, suffix, mode, mtype) = inspect.getmoduleinfo(filename)
except TypeError:
    print('Could not determine module type of {}'.format(
        filename))
else:
    mtype_name = {
        imp.PY_SOURCE: 'source',
        imp.PY_COMPILED: 'compiled',
    }.get(mtype, mtype)

    mode_description = {
        'rb': '(read-binary)',
        'U': '(universal newline)',
    }.get(mode, '')

    print('NAME   :', name)
    print('SUFFIX :', suffix)
    print('MODE   :', mode, mode_description)
    print('MTYPE  :', mtype_name)

Here are a few sample runs:

$ python3 inspect_getmoduleinfo.py example.py

NAME   : example
SUFFIX : .py
MODE   : r
MTYPE  : source

$ python3 inspect_getmoduleinfo.py readme.txt

Could not determine module type of readme.txt

$ python3 inspect_getmoduleinfo.py notthere.pyc

NAME   : notthere
SUFFIX : .pyc
MODE   : rb (read-binary)
MTYPE  : compiled

Inspecting Modules

It is possible to probe live objects to determine their components using getmembers(). The arguments are an object to scan (a module, class, or instance) and an optional predicate function that is used to filter the objects returned. The return value is a list of tuples with two values: the name of the member, and the type of the member. The inspect module includes several such predicate functions with names like ismodule(), isclass(), etc.

The types of members that might be returned depend on the type of object scanned. Modules can contain classes and functions; classes can contain methods and attributes; and so on.

inspect_getmembers_module.py
import inspect

import example

for name, data in inspect.getmembers(example):
    if name.startswith('__'):
        continue
    print('{} : {!r}'.format(name, data))

This sample prints the members of the example module. Modules have several private attributes that are used as part of the import implementation as well as a set of __builtins__. All of these are ignored in the output for this example because they are not actually part of the module and the list is long.

$ python3 inspect_getmembers_module.py

A : <class 'example.A'>
B : <class 'example.B'>
instance_of_a : <example.A object at 0x1013b1358>
module_level_function : <function module_level_function at
0x101395620>

The predicate argument can be used to filter the types of objects returned.

inspect_getmembers_module_class.py
import inspect

import example

for name, data in inspect.getmembers(example, inspect.isclass):
    print('{} : {!r}'.format(name, data))

Only classes are included in the output, now.

$ python3 inspect_getmembers_module_class.py

A : <class 'example.A'>
B : <class 'example.B'>

Inspecting Classes

Classes are scanned using getmembers() in the same way as modules, though the types of members are different.

inspect_getmembers_class.py
import inspect
from pprint import pprint

import example

pprint(inspect.getmembers(example.A), width=65)

Because no filtering is applied, the output shows the attributes, methods, slots, and other members of the class.

$ python3 inspect_getmembers_class.py

[('__class__', <class 'type'>),
 ('__delattr__',
  <slot wrapper '__delattr__' of 'object' objects>),
 ('__dict__',
  mappingproxy({'__dict__': <attribute '__dict__' of 'A'
objects>,
                '__doc__': 'The A class.',
                '__init__': <function A.__init__ at
0x10146ae18>,
                '__module__': 'example',
                '__weakref__': <attribute '__weakref__' of 'A'
objects>,
                'get_name': <function A.get_name at
0x10146aea0>})),
 ('__dir__', <method '__dir__' of 'object' objects>),
 ('__doc__', 'The A class.'),
 ('__eq__', <slot wrapper '__eq__' of 'object' objects>),
 ('__format__', <method '__format__' of 'object' objects>),
 ('__ge__', <slot wrapper '__ge__' of 'object' objects>),
 ('__getattribute__',
  <slot wrapper '__getattribute__' of 'object' objects>),
 ('__gt__', <slot wrapper '__gt__' of 'object' objects>),
 ('__hash__', <slot wrapper '__hash__' of 'object' objects>),
 ('__init__', <function A.__init__ at 0x10146ae18>),
 ('__le__', <slot wrapper '__le__' of 'object' objects>),
 ('__lt__', <slot wrapper '__lt__' of 'object' objects>),
 ('__module__', 'example'),
 ('__ne__', <slot wrapper '__ne__' of 'object' objects>),
 ('__new__',
  <built-in method __new__ of type object at 0x100229960>),
 ('__reduce__', <method '__reduce__' of 'object' objects>),
 ('__reduce_ex__', <method '__reduce_ex__' of 'object'
objects>),
 ('__repr__', <slot wrapper '__repr__' of 'object' objects>),
 ('__setattr__',
  <slot wrapper '__setattr__' of 'object' objects>),
 ('__sizeof__', <method '__sizeof__' of 'object' objects>),
 ('__str__', <slot wrapper '__str__' of 'object' objects>),
 ('__subclasshook__',
  <built-in method __subclasshook__ of type object at
0x10070e278>),
 ('__weakref__', <attribute '__weakref__' of 'A' objects>),
 ('get_name', <function A.get_name at 0x10146aea0>)]

To find the methods of a class, use the isfunction() predicate. The ismethod() predicate only recognizes bound methods of instances.

inspect_getmembers_class_methods.py
import inspect
from pprint import pprint

import example

pprint(inspect.getmembers(example.A, inspect.isfunction))

Only unbound methods are returned now.

$ python3 inspect_getmembers_class_methods.py

[('__init__', <function A.__init__ at 0x101b77e18>),
 ('get_name', <function A.get_name at 0x101b77ea0>)]

The output for B includes the override for get_name() as well as the new method, and the inherited __init__() method implemented in A.

inspect_getmembers_class_methods_b.py
import inspect
from pprint import pprint

import example

pprint(inspect.getmembers(example.B, inspect.isfunction))

Methods inherited from A, such as __init__(), are identified as being methods of B.

$ python3 inspect_getmembers_class_methods_b.py

[('__init__', <function A.__init__ at 0x101497e18>),
 ('do_something', <function B.do_something at 0x101497f28>),
 ('get_name', <function B.get_name at 0x101491048>)]

Inspecting Instances

Introspecting instances works in the same way as other objects.

inspect_getmembers_instance.py
import inspect
from pprint import pprint

import example

a = example.A(name='inspect_getmembers')
pprint(inspect.getmembers(a, inspect.ismethod))

The predicate ismethod() recognizes two bound methods from A in the example instance.

$ python3 inspect_getmembers_instance.py

[('__init__', <bound method A.__init__ of <example.A object at 0
x1018b21d0>>),
 ('get_name', <bound method A.get_name of <example.A object at 0
x1018b21d0>>)]

Documentation Strings

The docstring for an object can be retrieved with getdoc(). The return value is the __doc__ attribute with tabs expanded to spaces and with indentation made uniform.

inspect_getdoc.py
import inspect
import example

print('B.__doc__:')
print(example.B.__doc__)
print()
print('getdoc(B):')
print(inspect.getdoc(example.B))

The second line of the docstring is indented when it is retrieved through the attribute directly, but moved to the left margin by getdoc().

$ python3 inspect_getdoc.py

B.__doc__:
This is the B class.
    It is derived from A.


getdoc(B):
This is the B class.
It is derived from A.

In addition to the actual docstring, it is possible to retrieve the comments from the source file where an object is implemented, if the source is available. The getcomments() function looks at the source of the object and finds comments on lines preceding the implementation.

inspect_getcomments_method.py
import inspect
import example

print(inspect.getcomments(example.B.do_something))

The lines returned include the comment prefix with any whitespace prefix stripped off.

$ python3 inspect_getcomments_method.py

# This method is not part of A.

When a module is passed to getcomments(), the return value is always the first comment in the module.

inspect_getcomments_module.py
import inspect
import example

print(inspect.getcomments(example))

Contiguous lines from the example file are included as a single comment, but as soon as a blank line appears the comment is stopped.

$ python3 inspect_getcomments_module.py

# This comment appears first
# and spans 2 lines.

Retrieving Source

If the .py file is available for a module, the original source code for the class or method can be retrieved using getsource() and getsourcelines().

inspect_getsource_class.py
import inspect
import example

print(inspect.getsource(example.A))

When a class is passed in, all of the methods for the class are included in the output.

$ python3 inspect_getsource_class.py

class A(object):
    """The A class."""

    def __init__(self, name):
        self.name = name

    def get_name(self):
        "Returns the name of the instance."
        return self.name

To retrieve the source for a single method, pass the method reference to getsource().

inspect_getsource_method.py
import inspect
import example

print(inspect.getsource(example.A.get_name))

The original indent level is retained in this case.

$ python3 inspect_getsource_method.py

    def get_name(self):
        "Returns the name of the instance."
        return self.name

Use getsourcelines() instead of getsource() to retrieve the lines of source split into individual strings.

inspect_getsourcelines_method.py
import inspect
import pprint
import example

pprint.pprint(inspect.getsourcelines(example.A.get_name))

The return value from getsourcelines() is a tuple containing a list of strings (the lines from the source file), and a starting line number in the file where the source appears.

$ python3 inspect_getsourcelines_method.py

(['    def get_name(self):\n',
  '        "Returns the name of the instance."\n',
  '        return self.name\n'],
 24)

If the source file is not available, getsource() and getsourcelines() raise an IOError.

Method and Function Signatures

In addition to the documentation for a function or method, it is possible to ask for a complete specification of the arguments the callable takes, including default values. The signature() function returns a Signature instance containing information about the arguments to the function.

inspect_signature_function.py
import inspect
import example

sig = inspect.signature(example.module_level_function)
print('module_level_function{}'.format(sig))

print('\nParameter details:')
for name, param in sig.parameters.items():
    if param.kind == inspect.Parameter.POSITIONAL_ONLY:
        print('  {} (positional-only)'.format(name))
    elif param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
        if param.default != inspect.Parameter.empty:
            print('  {}={!r}'.format(name, param.default))
        else:
            print('  {}'.format(name))
    elif param.kind == inspect.Parameter.VAR_POSITIONAL:
        print('  *{}'.format(name))
    elif param.kind == inspect.Parameter.KEYWORD_ONLY:
        if param.default != inspect.Parameter.empty:
            print('  {}={!r} (keyword-only)'.format(
                name, param.default))
        else:
            print('  {} (keyword-only)'.format(name))
    elif param.kind == inspect.Parameter.VAR_KEYWORD:
        print('  **{}'.format(name))

The function arguments are available through the parameters attribute of the Signature. parameters is an ordered dictionary mapping the parameter names to Parameter instances describing the argument. In this example, the first argument to the function, arg1, does not have a default value, while arg2 does.

$ python3 inspect_signature_function.py

module_level_function(arg1, arg2='default', *args, **kwargs)

Parameter details:
  arg1
  arg2='default'
  *args
  **kwargs

The Signature for a function can be used by decorators or other functions to validate inputs, provide different defaults, etc. Writing a suitably generic and reusable validation decorator has one special challenge, though, because it can be complicated to match up incoming arguments with their names for functions that accept a combination of named and positional arguments. The bind() and bind_partial() methods provide the necessary logic to handle the mapping. They return a BoundArguments instance populated with the arguments associated with the names of the arguments of a specified function.

inspect_signature_bind.py
import inspect
import example

sig = inspect.signature(example.module_level_function)

bound = sig.bind(
    'this is arg1',
    'this is arg2',
    'this is an extra positional argument',
    extra_named_arg='value',
)

print('Arguments:')
for name, value in bound.arguments.items():
    print('{} = {!r}'.format(name, value))

print('\nCalling:')
print(example.module_level_function(*bound.args, **bound.kwargs))

The BoundArguments instance has attributes args and kwargs that can be used to call the function using the syntax to expand the tuple and dictionary onto the stack as the arguments.

$ python3 inspect_signature_bind.py

Arguments:
arg1 = 'this is arg1'
arg2 = 'this is arg2'
args = ('this is an extra positional argument',)
kwargs = {'extra_named_arg': 'value'}

Calling:
this is arg1this is arg1

If only some arguments are available, bind_partial() will still create a BoundArguments instance. It may not be fully usable until the remaining arguments are added.

inspect_signature_bind_partial.py
import inspect
import example

sig = inspect.signature(example.module_level_function)

partial = sig.bind_partial(
    'this is arg1',
)

print('Without defaults:')
for name, value in partial.arguments.items():
    print('{} = {!r}'.format(name, value))

print('\nWith defaults:')
partial.apply_defaults()
for name, value in partial.arguments.items():
    print('{} = {!r}'.format(name, value))

apply_defaults() will add any values from the parameter defaults.

$ python3 inspect_signature_bind_partial.py

Without defaults:
arg1 = 'this is arg1'

With defaults:
arg1 = 'this is arg1'
arg2 = 'default'
args = ()
kwargs = {}

Class Hierarchies

inspect includes two methods for working directly with class hierarchies. The first, getclasstree(), creates a tree-like data structure based on the classes it is given and their base classes. Each element in the list returned is either a tuple with a class and its base classes, or another list containing tuples for subclasses.

inspect_getclasstree.py
import inspect
import example


class C(example.B):
    pass


class D(C, example.A):
    pass


def print_class_tree(tree, indent=-1):
    if isinstance(tree, list):
        for node in tree:
            print_class_tree(node, indent + 1)
    else:
        print('  ' * indent, tree[0].__name__)
    return

if __name__ == '__main__':
    print('A, B, C, D:')
    print_class_tree(inspect.getclasstree(
        [example.A, example.B, C, D])
    )

The output from this example is the “tree” of inheritance for the A, B, C, and D classes. D appears twice, since it inherits from both C and A.

$ python3 inspect_getclasstree.py

A, B, C, D:
 object
   A
     D
     B
       C
         D

If getclasstree() is called with unique set to a true value, the output is different.

inspect_getclasstree_unique.py
import inspect
import example
from inspect_getclasstree import *

print_class_tree(inspect.getclasstree(
    [example.A, example.B, C, D],
    unique=True,
))

This time, D only appears in the output once:

$ python3 inspect_getclasstree_unique.py

 object
   A
     B
       C
         D

Method Resolution Order

The other function for working with class hierarchies is getmro(), which returns a tuple of classes in the order they should be scanned when resolving an attribute that might be inherited from a base class using the Method Resolution Order (MRO). Each class in the sequence appears only once.

inspect_getmro.py
import inspect
import example


class C(object):
    pass


class C_First(C, example.B):
    pass


class B_First(example.B, C):
    pass


print('B_First:')
for c in inspect.getmro(B_First):
    print('\t', c.__name__)
print()
print('C_First:')
for c in inspect.getmro(C_First):
    print('\t', c.__name__)

This output demonstrates the “depth-first” nature of the MRO search. For B_First, A also comes before C in the search order, because B is derived from A.

$ python3 inspect_getmro.py

B_First:
         B_First
         B
         A
         C
         object

C_First:
         C_First
         C
         B
         A
         object

The Stack and Frames

In addition to introspection of code objects, inspect includes functions for inspecting the runtime environment while a program is being executed. Most of these functions work with the call stack, and operate on “call frames.” Each frame record in the stack is a six element tuple containing the frame object, the filename where the code exists, the line number in that file for the current line being run, the function name being called, a list of lines of context from the source file, and the index into that list of the current line. Typically such information is used to build tracebacks when exceptions are raised. It can also be useful for logging or when debugging programs, since the stack frames can be interrogated to discover the argument values passed into the functions.

currentframe() returns the frame at the top of the stack (for the current function). getargvalues() returns a tuple with argument names, the names of the variable arguments, and a dictionary with local values from the frame. Combining them shows the arguments to functions and local variables at different points in the call stack.

inspect_getargvalues.py
import inspect


def recurse(limit):
    local_variable = '.' * limit
    print(limit, inspect.getargvalues(inspect.currentframe()))
    if limit <= 0:
        return
    recurse(limit - 1)
    return local_variable

if __name__ == '__main__':
    recurse(2)

The value for local_variable is included in the frame’s local variables even though it is not an argument to the function.

$ python3 inspect_getargvalues.py

2 ArgInfo(args=['limit'], varargs=None, keywords=None,
locals={'local_variable': '..', 'limit': 2})
1 ArgInfo(args=['limit'], varargs=None, keywords=None,
locals={'local_variable': '.', 'limit': 1})
0 ArgInfo(args=['limit'], varargs=None, keywords=None,
locals={'local_variable': '', 'limit': 0})

Using stack(), it is also possible to access all of the stack frames from the current frame to the first caller. This example is similar to the one shown earlier, except it waits until reaching the end of the recursion to print the stack information.

inspect_stack.py
import inspect


def show_stack():
    for level in inspect.stack():
        (frame, filename, line_num,
         func, src_code, src_index) = level
        print('{}[{}]\n  -> {}'.format(
            filename,
            line_num,
            src_code[src_index].strip(),
        ))
        print(inspect.getargvalues(frame))
        print()


def recurse(limit):
    local_variable = '.' * limit
    if limit <= 0:
        show_stack()
        return
    recurse(limit - 1)
    return local_variable

if __name__ == '__main__':
    recurse(2)

The last part of the output represents the main program, outside of the recurse() function.

$ python3 inspect_stack.py

inspect_stack.py[10]
  -> for level in inspect.stack():
ArgInfo(args=[], varargs=None, keywords=None,
locals={'src_index': 0, 'frame': <frame object at 0x100435a48>,
'line_num': 10, 'func': 'show_stack', 'level':
FrameInfo(frame=<frame object at 0x100435a48>,
filename='inspect_stack.py', lineno=10, function='show_stack',
code_context=['    for level in inspect.stack():\n'], index=0),
'src_code': ['    for level in inspect.stack():\n'], 'filename':
'inspect_stack.py'})

inspect_stack.py[25]
  -> show_stack()
ArgInfo(args=['limit'], varargs=None, keywords=None,
locals={'local_variable': '', 'limit': 0})

inspect_stack.py[27]
  -> recurse(limit - 1)
ArgInfo(args=['limit'], varargs=None, keywords=None,
locals={'local_variable': '.', 'limit': 1})

inspect_stack.py[27]
  -> recurse(limit - 1)
ArgInfo(args=['limit'], varargs=None, keywords=None,
locals={'local_variable': '..', 'limit': 2})

inspect_stack.py[31]
  -> recurse(2)
ArgInfo(args=[], varargs=None, keywords=None,
locals={'__cached__': None, '__package__': None, '__builtins__':
<module 'builtins' (built-in)>, 'show_stack': <function
show_stack at 0x101857f28>, 'recurse': <function recurse at
0x101c83620>, '__name__': '__main__', '__loader__':
<_frozen_importlib_external.SourceFileLoader object at
0x1018aa828>, '__file__': 'inspect_stack.py', 'inspect': <module
'inspect' from '.../lib/python3.5/inspect.py'>, '__doc__':
'Inspecting the call stack.\n', '__spec__': None})

There are other functions for building lists of frames in different contexts, such as when an exception is being processed. See the documentation for trace(), getouterframes(), and getinnerframes() for more details.

Command Line Interface

The inspect module also includes a command line interface for getting details about objects without having to write out the calls in a separate Python program. The input is a module name and optional object from within the module. The default output is the source code for the named object. Using the --details argument causes metadata to be printed instead of the source.

$ python3 -m inspect -d example

Target: example
Origin: .../example.py
Cached: .../__pycache__/example.cpython-35.pyc
Loader: <_frozen_importlib_external.SourceFileLoader object at 0
x101d25668>



$ python3 -m inspect -d example:A

Target: example:A
Origin: .../example.py
Cached: .../__pycache__/example.cpython-35.pyc
Line: 17



$ python3 -m inspect example:A.get_name

    def get_name(self):
        "Returns the name of the instance."
        return self.name

See also