Plugins in Python

David LeBlanc whisper at oz.nospamnet
Wed Jun 13 21:05:58 CEST 2001


[This followup was posted to comp.lang.python and a copy was sent to the 
cited author.]

In article <u7kyh46w7.fsf at ctwd0143.fitlinxx.com>, db3l at fitlinxx.com 
says...
> David LeBlanc <whisper at oz.nospamnet> writes:
> 
> > How would one generally code something that would look at some dir (or 
> > list of dirs), and dynamically load .py or .pyc modules found there that 
> > where not previously known to the program. Obviously following a standard 
> > API...
> 
> I tend to make plugins for an application a package.
> 
> One approach is that the __init__ file in the package can inspect the
> package directory for other modules, and then use __import__ to import
> them.  I normally then populate a well-known dictionary within the
> __init__ module that applications can use to determine what plugins
> were loaded.  You can also decide to set up the modules for lazy
> loading using a proxy class if you want to avoid the overhead of
> actually importing the plugin until needed.
> 
> Note that one major negative with this approach is that it confuses
> Python installation tools like py2exe and installer, as they can't
> follow the dynamic importing, and also because the directory structure
> may not be similar during execution.
> 
> So in the cases that I need to package things, I instead write my
> __init__ such that it contains explicit imports for supported plugins,
> but nothing more.  Then instead of looping through the filesystem, I
> loop through my local dictionary looking for modules, and then import
> them (or call well defined entry points in them to let them identify
> what they support).  This does mean they all get imported, but it
> works regardless of directory structure, and can be packaged.
> 
> --
> -- David
> 
Thanks David! That's exactly what i'm looking for. Python the ever 
flexible snake! I sort of thought that (dunno why, just didn't occur to 
me) that import wouldn't take a variable as in:

mymodule = "c:/boo/yikes.py"
import mymodule

I gather that's what you mean?

>From what you're telling me, the general idea is (or could be)?:

import standardplugin1
import standardplugin2
#etc

# Inspect some known directory or set of directories for *.py files
plugins = getplugins()	# assume "./plugins"

# alternative 1
for plug in plugins
	import plug
		try
			plug.registerplugin()
			# or if not plug.hasmethod("registerplugin")
			# is this possible? hasattribute()?
		except
			unload plug

# alternative 2 - this one seems potentially faster or maybe less memory 
# intensive - does unload really reclaim memory used by the module 
# unloaded?
for plug in plugins
	if grep("registerplugin" plug) == 1 # or whatever means is 
							# appropriate to check
							# perhaps arranging a comment
							# as the first line of the file
							# would be fastest and simplest
							# of all - and extra info too!
		import plug
		plug.registerplugin()

# on with the show...

-------------------------

I take your point about the installer issue, and it's something i'd have 
to live with I guess. I want to be able to dynamically download a new 
plugin and have the user take no further action then putting it in the 
plugins directory. This might even be done automagically as part of a 
dynamic update or install feature and then the user couldn't even get 
putting it in the right directory wrong ;-)

Thanks for the help David and to the other posters too!

Regards,

David LeBlanc

P.S. Tim Delany's idea only works when the list of plugins is known in 
advance.



More information about the Python-list mailing list