5

I was wondering how I can provide an API for my Python program to enable others to extend it with plugins. I thought about something like from myProgram.plugins import aClassToExtendByOthers, registerThatClass. But I have no idea how to provide this.

I could use an exec statement within my loadPlugins function for every plugin in the plugins-folder, but this would not enable importing stuff I would like to provide for people to write those plugins.

Niklas R
  • 16,299
  • 28
  • 108
  • 203
  • Here's [several ways](http://zoomq.qiniudn.com/ZQScrapBook/ZqFLOSS/data/20060526140550/#command-dispatch-pattern) to implement the command dispatch pattern in Python. – martineau Sep 15 '13 at 10:19

2 Answers2

2

For a system that I use in several of my programs, I define a directory of plugins, and provide a base plugin class for all plugins to subclass. I then import all modules in the directory, and selectively initialize (by checking to see if they subclass my base plugin class), and store instances of plugins in a dictionary (or list). I have found that the command dispatch pattern has worked effectively for me as a way to structure the plugins and pass events. The base plugin (or another optional interface class) can provide the methods that the plugin needs to interact with the application. I hope this helps. It may not be the best way to do it, but it has worked for me.

In addition, you could do additional filtering, such as requiring plugin files to have a prefix (e.g. __plug_file.py__ and __plug_other.py__).

martineau
  • 119,623
  • 25
  • 170
  • 301
Michael Smith
  • 1,847
  • 2
  • 19
  • 19
  • So you simply use an exec statement or did I understand you wrong ? – Niklas R Jul 04 '11 at 19:03
  • No, I import the modules using the \_\_import\_\_ function, and then use inspect to list all classes in the module that I have just imported. This system does allow for plugins to use other modules, which you said was one of your concerns. Just using exec in these cases can be dangerous. – Michael Smith Jul 04 '11 at 19:04
  • Hm, sure this is better than exec. But how do I provide that the pluginwriter can use classes I provide for him by importing them ? (as said in the question something like _from myProgram.plugins import extensiblePluginClass_) – Niklas R Jul 04 '11 at 19:16
  • Yeah, just make some file with the base classes and import it in both the main program, and each plugin file. The way I do it, is that I determine whether or not the plugin directory is valid by the presence of a file named \_\_plug\_\_.py, which has the necessary classes. Alternatively, you could just define the classes in a file that is in your packages, and import from that. The reason I put the file in the directory, is that I use my system for multiple things, and don't want to manually modify the source of the system. – Michael Smith Jul 04 '11 at 19:24
0

you can use imp module (see docs.python.org)

sys.path.insert(0, pluginsDir)
lst = map(lambda x: os.path.splitext(os.path.basename(x))[0], glob.glob(os.path.join(pluginsDir, "*.py")))
for module in lst:
try:
  f, fn, d = imp.find_module(module,[pluginsDir])
  loaded = imp.load_module(module, f, fn, d)

for fully functional example see the loader of ojuba control center

http://git.ojuba.org/cgit/occ/tree/OjubaControlCenter/loader.py

Muayyad Alsadi
  • 1,506
  • 15
  • 23