在Python <3.6中,元类方法对于此问题很有用(请参阅@quasoft对于Python
3.6+的回答)。它非常简单,并且可以自动对任何导入的模块起作用。另外,可以很轻松地将复杂的逻辑应用于插件注册。这个需要:
在元类方法的工作原理如下所示:
1)定义了一个自定义
PluginMount元类,其中维护了所有插件的列表
2)
Plugin定义一个将
PluginMount其设置为元类的类
3)例如,当导入一个源自
Plugin-的对象时
MyPlugin,它将触发
__init__该元类上的方法。这将注册插件并执行任何特定于应用程序的逻辑和事件订阅。
或者,如果您将
PluginMount.__init__逻辑放入其中,则在创建派生类
PluginMount.__new__的新实例时将调用该逻辑
Plugin。
class PluginMount(type): """ A plugin mount point derived from: http://martyalchin.com/2008/jan/10/simple-plugin-framework/ Acts as a metaclass which creates anything inheriting from Plugin """ def __init__(cls, name, bases, attrs): """Called when a Plugin derived class is imported""" if not hasattr(cls, 'plugins'): # Called when the metaclass is first instantiated cls.plugins = [] else: # Called when a plugin class is imported cls.register_plugin(cls) def register_plugin(cls, plugin): """Add the plugin to the plugin list and perform any registration logic""" # create a plugin instance and store it # optionally you could just store the plugin class and lazily instantiate instance = plugin() # save the plugin reference cls.plugins.append(instance) # apply plugin logic - in this case connect the plugin to blinker signals # this must be defined in the derived class instance.register_signals()
然后是一个基本的插件类,如下所示:
class Plugin(object): """A plugin which must provide a register_signals() method""" __metaclass__ = PluginMount
最后,一个实际的插件类如下所示:
class MyPlugin(Plugin): def register_signals(self): print "Class created and registering signals" def other_plugin_stuff(self): print "I can do other plugin stuff"
可以从已导入的任何python模块访问插件
Plugin:
for plugin in Plugin.plugins: plugin.other_plugin_stuff()
查看完整的工作示例



