无缝动态插件加载

时间:2012-10-26 16:45:27

标签: python plugins dynamic module namespaces

我正在为一个框架开发一个可扩展的插件子系统,但我仍然坚持如何让系统从插件本身动态无缝地加载插件。我已经知道如何添加插件(可能会使用入口点)。举个例子:

pluga.py

from framework.plug_lib import plugin

@plugin
def foo():
    return 2

@plugin
def bar():
    return foo()

plugb.py

from framework.plug_lib import plugin

@plugin
def foo():
    return 3

framework.plug_lib.py

loaded_plugins = {}

class Plugin(object):
    def __init__(self, plug): #note plug could be class, function, method, etc
        self.plug = plug
    def plug_load(self):
        loaded_plugins[self.plug.__name__] = self.plug
    def plug_get_loaded_version(self):
        try:
            return loaded_plugins[self.plug.__name__]
        except KeyError:
            raise RuntimeError('No plugin %s loaded.' % self.plug.__name__)

def plugin(plug):
    return Plugin(plug)

def load(plugin_path):
    # get plugin by searching entry-points, other basic logic
    plugin.plug_load()

用法示例:

from framework.plug_lib import load, loaded_plugins

load('pluga.foo')
load('pluga.bar')
loaded_plugins['bar']() # 2

from framework.plug_lib import load, loaded_plugins

load('plugb.foo')
load('pluga.bar')
loaded_plugins['bar']() # 3

这简化为试图简明地说明问题。在真实的框架中,有多种不同类型的插件,它们都会转到不同的loaded_plugin类似物。如果插件的容器是一个类,我可能想办法将这个插入描述符或其他东西,但部分原因是重构一些包装当前插件的样板代码。我可以自定义模块本身检查它自己的命名空间的方式,并在插件模块本身中没有或最多只有一个简单的行检索它的成员吗?我基本上需要在模块本身上等同于__getattribute__的东西,所以我可以使Plugins表现得像穷人的描述符,并且每当尝试访问除{{1}之外的任何内容时都返回self.plug_get_loaded_version()我认为,方法,但我不知道如何做到这一点。也许打包时间代码(在setup.py中的东西),但我认为你不能在开发模式下处理已安装的软件包,而不是每次都重建。那里有什么想法吗?

0 个答案:

没有答案