元类方法 在 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'):
cls.plugins = []
else:
cls.register_plugin(cls)
def register_plugin(cls, plugin):
"""Add the plugin to the plugin list and perform any registration logic"""
instance = plugin()
cls.plugins.append(instance)
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"
插件可以从导入了Plugin
的任何Python模块中访问:
for plugin in Plugin.plugins:
plugin.other_plugin_stuff()
查看完整的工作示例
load_plugins
和predicate
函数。这是我建议的方法。 - Wessie