Best practices for dynamically loading plugins at startup

Jeff Schwab jeffrey.schwab at rcn.com
Sun Sep 25 23:33:03 EDT 2005


Christoph Haas wrote:
> Dear coders...
> 
> I'm working on an application that is supposed to support "plugins".
> The idea is to use the plugins as packages like this:
> 
> Plugins/
>   __init__.py
>   Plugin1.py
>   Plugin2.py
>   Plugin3.py
> 
> When the application starts up I want to have these modules loaded
> dynamically. Users can put their own plugin modules into the
> Plugins/ directory and the application should know about it.
> 
> Since I don't know which plugins have been put into that directory
> I cannot just "import Plugin1, Plugin2, Plugin3" in the "__init__.py".
> So I need to find out the *.py there and load them during startup.
> I could do that with a "walk" over that directory.
> 
> Each plugin is supposed to be a class derived from a general
> "Plugin" superclass. I just don't know how to 'register' every
> plugin. The main application needs to know which plugin classes
> there are. On IRC I was recommended walking through all objects
> and finding out if the class is a subclass of "Plugin". Another
> person recommended using metaclasses to automatically register
> the plugin in a global list.
> 
> Since I have only little real-life Python knowledge I wonder what the
> best practice for this kind of problem is.
> 
> I looked at the "supybot" IRC bot to get an idea how plugins are handled
> there. Unfortunately it was still a bit over my (python) head.

I recently came up against this exact problem.  My preference is to have 
the plugin writer call a method to register the plugins, as this allows 
him the most control.  Something along these lines:

	class A_plugin(Plugin):
		...

	class Another_plugin(Plugin):
		...

	register( A_plugin )
	register( Another_plugin, optional_custom_registration_parameters )


I also like the Mark Pilgrim approach of having the plugins follow a 
strict naming convention, then searching for them with hasattr or by 
grepping each plugin module's namespace.  E.g., I have a build script 
written in python that I use instead of the "make" utility; for each 
target, I define a method called make_<target> in my plugin module, like 
this:

	function = "make_%s" % target
	if hasattr(module, function):
		getattr(module, function)()
	else:
		print >>sys.stderr, 'Unknown target "%s"' % target



More information about the Python-list mailing list