Monday, January 26, 2009

Python Plugin Frameworks

Updated to include pointers to the PyUtilib Component Architecture and PnP.

Various Python projects I am working on could benefit from the use of a Plug-in framework.  However, there does not appear to be a standard Python plug-in framework, though there are some mature packages that support plug-ins.

Here's a summary of my recent web research:
  • yapsy - This is a simple plug-in framework that was designed specifically to support plug-ins with no external dependencies.
  • Mary Alchin describes a simple plugin framework, with a similar goal.  His classes provide an API for the plugins, with few supporting features (e.g. searching for plugins).
  • AndrĂ© Roberge has a series of posts that describe the application of plugins to refactor a simple calculator application.  The goal of this is to illustrate the requirements for plugin frameworks, with the goal of identifying best practices for plugins. There are some interesting replies to this post, which consider implementations of the plugins he proposes in zope and grok. Both of these pull in quite a few libraries, which begs the question of whether it makes sense for external users to rely on these components for only plugin support.
  • Enthought's Envisage project includes a framework for building extensible, pluggable applications.  The enthough.envisage package defines these capabilities, and there is nice documentation here.
  • Trac and Zope are frameworks that incorporate plug-ins, and these capabilities may be modular enough for use in other applications. Trac's component architecture is detailed in the Trac wiki pages. Zope's plug-ins appear to be called products (see also here). Martin Aspeli describes his experience writing Trac plug-ins and contrasts them with Zope.
  • The PyUtilib Component Architecture (PCA) is a component architecture in Python that is derived from the Trac component framework. One important extension was to support both singleton and non-singleton plugins. Singleton plugins are created immediately when the plugin module is loaded, which is well-suited for persistent applications like Trac. However, many other applications need to employ plugins "on demand", which need to be explicitly constructed by the end-user. (See the PyUtilib wiki for further details.)
  • Plug n' PLay (PnP) is a Generic plug-in system inspired by Trac's internal component management. PnP is roughly a implementation of the Observer pattern (http://en.wikipedia.org/wiki/Observer_pattern).
     
These resources highlight one reason why there is not a standard Python plug-in framework: there are a variety of different capabilities that a user may want, and the complexity of the framework generally increases as these new capabilities are added (e.g. security, API validation, etc). Another item that seems clear is that while a variety of packages support plug-ins, many of them do not use them in a modular fashion.  Thus, it is difficult to reuse sophisticated plug-in frameworks without incorporating a lot of extraneous code.

1 comment: