Categories
Computers Programming Python

Dynamic Modules in Python

I have defined a rather simple class for an XML proxy server to facilitate interacting with a blog. Right now, I’ve implemented a WordPress version so I can work with my own blog. Theoretically, it should be possible to implement other classes specific to other blog types thus making my program more general, and useful to others.

What I hadn’t figured out was how to structure the code so as to minimize monkeying around with multiple files when adding the new class. My goal was to come up with a structure that simply called for adding a module to extend the functionality.

Today, I finally came up with something and it utilizes the dynamic module loading capabilities of python.

First, I structured this particular section of code as a package. Then, in the __init__.py module I created the following chunk of code:

modules = {}

filepath = '/path/to/package'
sys.path.insert(1, filepath)
cwd = os.path.abspath(os.curdir)
filefilter = re.compile("([a-zA-Z_]+)-proxy")
os.chdir(filepath)
for f in os.listdir(os.curdir):
    modulename, ext = os.path.splitext(f)
    if ext == ".py":
        m = filefilter.match(modulename)
        if m:
            modules[m.group(1)] = __import__(modulename)

os.chdir(cwd)

Because I haven’t added my program as part of the standard python search path, I had to add an absolute path to the package directory into the system search path when this program is running. From there, the code builds a list of files in the package directory and then filters them for a specific name format. Once it has that, it imports that module using the __import__ call and stashes the module into a modules dictionary for retrieval later.

The other piece of code in the __init__.py module is the following:

def getProxy(blogtype, url, user, password):
    if blogtype not in modules:
        return None

    return modules[blogtype].getInst(url, user, password)

Because I stashed away a reference to the module in the dict, I can now recall just that module when I need a proxy object. The corresponding getInst call, as one might guess, returns an instance of the proxy class.

So now, to add support for a new blog type, I simply have to create a module in the package directory that:

  1. Implements a proxy class with all the appropriate methods as defined by a base class.
  2. Implements a function that returns an instance of the proxy class.
  3. Is namded using a ‘blogtype’-proxy.py format; where ‘blogtype’ might be ‘blogger’ or something like that.

Some of the details took awhile to work out. Specifically, the path definitions. There may be a better way to achieve this sort of functionality as well, but I was pleased once I got this working.

UPDATE: Corrected code. The cwd path saved off was not properly restored previously because it wasn’t saved properly.

Leave a Reply

Your email address will not be published. Required fields are marked *