元类方法对于 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()
查看完整的工作示例