Introspection in Python


Bhaskar S 08/10/2014


Introduction

Every entity in Python is an object, be it a module, a package, a class, a method, or a type. Introspection is an ability to look into an object (modules, classes, methods, etc) in memory and glean information (or manipulate information) dynamically at run-time.

In this article, we will explore introspection using a simple example to perform the following:

The following is a simple python module named MyContact.py that defines a class called MyContact:

MyContact.py
#
# Module: MyContact.py
#

# ----- Start Definition the class Contact -----

class MyContact:
    "This class encapsulates contact information"

    def __init__(self):
        self.email = ""
        self.home = ""
        self.mobile = ""

    def getEmail(self):
        return self.email

    def setEmail(self, email):
        self.email = email

    def getHome(self):
        return self.home

    def setHome(self, home):
        self.home = home

    def getMobile(self):
        return self.mobile

    def setMobile(self, mobile):
        self.mobile = mobile
        
    def __str__(self):
        return "Email: " + self.email + ", Home: " + self.home + ", Mobile: " + self.mobile

To dynamically load a python module at run-time, use the import_module method from the standard importlib python module.

The import_module(name, package=None) method takes as arguments a module name and an optional package name.

If the specified module name does not exist, an ImportError exception is thrown.

The following is the python code snippet to dynamically load a specified module:

Load Module (Code Snippet)
my_module = None
try:
    my_module = importlib.import_module(mod_name)
except ImportError:
    print "Module not found -", mod_name
    sys.exit(1)

To check a python object (module or class) at run-time for existence of a named attribute (class, method, or field), use the standard hasattr method.

The hasattr(object, name) method takes as arguments an object (module or class) and an attribute name.

If the specified attribute name does not exist, the method returns a False.

The following is the python code snippet to dynamically check for a specified method:

Check Method (Code Snippet)
get_email_func = None
if hasattr(contact, func_name) == False:
    print "Method not found -", func_name
    sys.exit(1)

To get the value of a named attribute (class, method, or field) at run-time, use the standard getattr method.

The getattr(object, name) method takes as arguments an object (module or class) and an attribute name.

If the named attribute is for a field, the result is the value of that field.

If the specified named attribute does not exist, an AttributeError exception is thrown.

The following is the python code snippet to dynamically get the value of a specified field:

Get Value (Code Snippet)
print "Mobile:", getattr(contact, attr_name)

Putting it all together, the following is a simple python script named MyDynamic.py that dynamically loads the python module MyContact.py, creates a instance of the class MyContact, invokes the method getEmail(), and gets the value of the field mobile:

MyDynamic.py
#
# Dynamic Loading and Introspection
#

import sys, importlib

mod_name = 'MyContact'
class_name = 'MyContact'
func_name = 'getEmail'
attr_name = 'mobile'

my_module = None
try:
    my_module = importlib.import_module(mod_name)
except ImportError:
    print "Module not found -", mod_name
    sys.exit(1)

my_class = None
if hasattr(my_module, class_name) == False:
    print "Class not found -", class_name
    sys.exit(1)
    
my_class = getattr(my_module, class_name)

contact = my_class()
contact.setEmail("john.doe@space.com")
contact.setHome("123-456-7890");
contact.setMobile("987-654-3210");

print contact

get_email_func = None
if hasattr(contact, func_name) == False:
    print "Method not found -", func_name
    sys.exit(1)
    
get_email_func = getattr(contact, func_name)

print "Email:", get_email_func()

if hasattr(contact, attr_name) == False:
    print "Attribute not found -", attr_name
    sys.exit(1)

print "Mobile:", getattr(contact, attr_name)

Executing MyDynamic.py results in the following output:

Output

Email: john.doe@space.com, Home: 123-456-7890, Mobile: 987-654-3210
Email: john.doe@space.com
Mobile: 987-654-3210

References

Python Quick Notes :: Part - 1

Python Quick Notes :: Part - 2

Python Quick Notes :: Part - 3

Python Quick Notes :: Part - 4

Python Quick Notes :: Part - 5

Python Quick Notes :: Part - 6