plug-ins

Dave Brueck dave at pythonapocrypha.com
Sat May 7 19:09:03 EDT 2005


Eric Nieuwland wrote:
> The app I'm working on keeps getting new transforms and I'm tired of 
> adding them by hand. So here it goes:
> Can anyone provide me with clues/examples/references on how to create a 
> plug-in framework?

The biggest task is defining the interface between your app and the plugins - 
you need to decide at what points plugins can interact with your application, 
what data from your application they'll need to have access to, etc. You'll also 
need to decide how your app becomes aware of new plugins - perhaps the data 
specifies it, or a config file. IOW, most of the initial work is just deciding 
on a convention you want to follow. Here is a simple example:

"Plugins are Python modules that are placed in the <app>/plugins directory. A 
plugin may optionally have an Init() function that is called when the plugin is 
first loaded. A plugin is required to have a Process() function. This function 
takes an input buffer and return a transformed output buffer."

Here's some quickie code to load a plugin (untested):

import new

def LoadPlugin(name):
   'Loads a plugin and returns a plugin module object'
   # TODO: Decide on and implement an error-handling convention
   # Create a new module
   m = new.module(name)
   source = file('plugins/%s' % name).read()
   exec source in m.__dict__

   assert hasattr(m, 'Process'), 'Plugin %s has no Process function' % name
   # Optionally run its Init function
   if hasattr(m, 'Init'):
     m.Init()

   return m

If you need plugins at different times, you could have a plugin cache:

pluginCache = {} # name -> plugin module
def GetPlugin(name):
   'Returns the named plugin from the cache, creating it if needed'
   try:
     return pluginCache[name]
   except KeyError:
     plugin = pluginCache[name] = LoadPlugin(name)
     return plugin

You might use a plugin like this:

def Transform(name, data):
   'Applies the named transform to the data and returns the result'
   plugin = GetPlugin(name)
   return plugin.Process(data)

In practice, your plugins will probably have a much richer interface. You may 
even decide to have an "application" object of some sort that you can pass to 
the plugins to provide services to them (logging facility, supporting routines 
that many plugins need, etc.). Instead of a module-based approach, you may 
instead decide that all plugins inherit from a plugin base class.

-Dave



More information about the Python-list mailing list