Python inspect module

Python’s inspect module provides the introspection of live objects and the source code of the same.

It also provides the introspection of the classes and functions used throughout the program.

The inspect module provides the user to make use of functions/methods in it to fetch the source code for the same, extract and parse the needed library documentation.

This module is used to fetch information about the functions, classes and modules in the particular user’s program. This is made available by performing inspection on the module’s properties, classes/methods of the module, etc.


Python inspect module functionalities

  • Introspection of a module
  • Introspection of classes in a module
  • Introspection of methods/functions in a class
  • Introspection of objects of a class
  • Retrieval of source of a class
  • Retrieval of source of a method/function
  • Fetching the method signature
  • Documentation of Strings for a class
  • Introspecting Class Hierarchies
  • Introspection of Frames and Stacks in the run-time environment

1. Introspection of a module

Initially, we need to create a sample module along with classes/functions for introspection i.e. test.py

test.py


def funct(arg1, arg2 = 'default', *args):
    #module-level function
    x = arg1 * 1
    return x

class P(object):


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

    def get_city(self):

        return self.city

obj_p = P('sample_instance')

class Q(P):



    def country(self):
       return ("Hello")
    def get_country(self):

        return 'Q(' + self.city + ')'

Then we will introspect the created module using inspect.getmembers() function.

Note: The python file containing the sample module and the file containing the introspection code should be placed under the same directory.

Code for Introspection of Module:

import inspect
import test

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

Output:

P : <class 'test.P'>
Q : <class 'test.Q'>
funct : <function funct at 0x000001ED62A2EAF0>
obj_p : <test.P object at 0x000001ED62A6A640>

2. Introspection of classes in a module

The getmembers() function along with the isclass property identifier is used to inspect the classes within a module.

import inspect
import test

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

Output:

P : <class 'test.P'>
Q : <class 'test.Q'>

3. Introspection of methods/functions in a class

The getmembers() function along with the isfunction property identifier is used to inspect the classes within a module.

import inspect
from pprint import pprint
import test

pprint(inspect.getmembers(test.P, inspect.isfunction))

Output:

[('__init__', <function P.__init__ at 0x000001D519CA7CA0>),
 ('get_city', <function P.get_city at 0x000001D519CA7D30>)]

4. Introspection of objects of a class

import inspect
from pprint import pprint
import test

result = test.P(city='inspect_getmembers')
pprint(inspect.getmembers(result, inspect.ismethod))

Output:

[('__init__',
  <bound method P.__init__ of <test.P object at 0x00000175A62C5250>>),
 ('get_city',
  <bound method P.get_city of <test.P object at 0x00000175A62C5250>>)]

5. Retrieval of source of a class

The getsource() functions returns the source of a particular module/class.

import inspect
import test

print(inspect.getsource(test.Q))

Output:

class Q(P):

    def country(self):
       return ("Hello")
    def get_country(self):

        return 'Q(' + self.city + ')'

6. Retrieval of source of a method/function

import inspect
import test

print(inspect.getsource(test.Q.get_city))

Output:

def get_city(self):

        return self.city

7. Fetching the method signature

The inspect.signature() method returns the signature of the method, thus making it easy for the user to understand the kind of arguments passed to the method.

import inspect
import test

print(inspect.signature(test.funct))

Output:

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

8. Documentation of Strings for a class

The inspect module’s getdoc() function extracts a particular class and its functions to represent to the end-user.

import inspect
import test

print('P.__doc__:')
print(test.P.__doc__)
print()
print('Documentation String(P):')
print(inspect.getdoc(test.P))

Output:

P.__doc__:
Implementation of class P

Documentation String(P):
Implementation of class P

9. Introspecting Class Hierarchies

The getclasstree() method returns the hierarchy of the classes and its dependencies. It creates a tree-structure using tuples and lists from the given classes.

import inspect
import test

class S(test.Q):
    pass

class T(S, test.P):
    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__ )


if __name__ == '__main__':
    print( 'P, Q, S, T:')
    print_class_tree(inspect.getclasstree([test.P, test.Q, S, T]))

Output:

P, Q, S, T:
 object
   P
     T
     Q
       S
         T

10. Introspection of Frames and Stacks in the run-time environment

The inspect module also inspects the function’s dynamic environment of the program during its execution. The functions mostly work with call stack and call frames.

currentframe() depicts the frame at the top of the stack for the current executing function. getargvalues() results as a tuple with the names of the arguments, and a dicttionary of local values from the frames.

import inspect

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

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

Output:

4 ArgInfo(args=['threshold'], varargs=None, keywords=None, locals={'threshold': 4, 'x': '....'})
3 ArgInfo(args=['threshold'], varargs=None, keywords=None, locals={'threshold': 3, 'x': '...'})
2 ArgInfo(args=['threshold'], varargs=None, keywords=None, locals={'threshold': 2, 'x': '..'})
1 ArgInfo(args=['threshold'], varargs=None, keywords=None, locals={'threshold': 1, 'x': '.'})
0 ArgInfo(args=['threshold'], varargs=None, keywords=None, locals={'threshold': 0, 'x': ''})

Conclusion

Thus, in this article, we have understood the functionalities offered by the inspect module of Python.


References