NOTE: This is an old article I wrote in January 2008, it’s still relevant today. It was originally posted on luckydonkey.com which I am in the process of retiring.
Sometimes you need to write code that loads python at runtime. Plugin architectures are a good example of this. Plugins allow extensibility but more importantly (for me at least) they enforce a strict API. Anyway, I’ve written this code a few times so I thought I’d modularize it.
The specific bit of code I am going to post is the python code to look for and load a series of python plugins. Plugins (in this case) are just classes that are subclasses of the Plugin base class. This plugin base class dictates the API that all plugins must implement. Here is an example plugin abstract base class
"""called before the plugin is asked to do anything"""
"""called to allow the plugin to free anything"""
"""do whatever it is the plugin does"""
Here the is code to look for and return a list of classes that can be instantiated:
def find_subclasses(path, cls):
Find all subclass of cls in py files located below path
(does look in sub directories)
@param path: the path to the top level folder to walk
@type path: str
@param cls: the base class that all subclasses should inherit from
@type cls: class
@return: a list if classes that are subclasses of cls
log.debug("searching %s" % (modulename))
#walk the dictionaries to get to the last one
for m in modulename.split('.')[1:]:
#look through this dictionary for things
#that are subclass of Job
#but are not Job itself
for key, entry in d.items():
if key == cls.__name__:
if issubclass(entry, cls):
log.debug("Found subclass: "+key)
#this happens when a non-type is passed in to issubclass. We
#don't care as it can't be a subclass of Job if it isn't a
for root, dirs, files in os.walk(path):
for name in files:
if name.endswith(".py") and not name.startswith("__"):
path = os.path.join(root, name)
modulename = path.rsplit('.', 1).replace('/', '.')
and here is how you would call it:
classes = find_subclasses("./pluginsfolder/", Plugin)
#lets create an instance of the first class
inst = classes()
So there you go, create folder of python files with classes in them that subclass the Plugin class and you are away.
The original article had a number of insightful comments, I’ve included all their corrections but unfortunately not the original comments. Thanks to all those who contributed to make this a better article.