我对python相对较新(已经做了一些1h脚本,比如一个小小的网络服务器或本地网络聊天),并想在其中编写一个插件管理器。 我的想法是,有一个插件接口,具有以下功能:
getDependencies -> all dependencies of the plugin to other plugins
getFunctions -> all functions that this plugin introduces
initialize -> a function that is called when loading the plugin
(我可以想象在依赖关系上有一个拓扑排序算法来决定插件初始化的顺序。)
我想实现多线程,这意味着每个插件都在自己的线程中运行,该线程具有一个将按顺序执行的函数调用的工作队列。当一个插件调用另一个插件的函数时,它会调用管理器,而管理器又会将函数调用插入到另一个插件的队列中。
此外,经理应该提供某种事件系统,其中插件可以注册自己的事件并成为其他人事件的听众。
此外,我希望能够在代码更改或其线程崩溃时重新加载插件,而无需关闭管理器/应用程序。我已经结合这一点阅读了How do I unload (reload) a Python module?。
再次说明:管理员不应提供任何其他功能,而不是支持其插件之间具有通用通信接口,并行运行的能力(以多线程方式运行而不需要插件知道这个)并恢复更新/崩溃的插件。
所以我的问题是:是否可以在python中执行此操作?如果是,那么粗略草图中是否存在设计错误?我很感激对此有任何好的建议。
答案 0 :(得分:6)
在最基本的层面上,首先,您需要提供一个基本的插件类,它是为您的应用程序编写的所有插件的基础。
接下来我们需要全部导入它们。
class PluginLoader():
def __init__(self, path):
self.path = path
def __iter__(self):
for (dirpath, dirs, files) in os.walk(self.path):
if not dirpath in sys.path:
sys.path.insert(0, dirpath)
for file in files:
(name, ext) = os.path.splitext(file)
if ext == os.extsep + "py":
__import__(name, None, None, [''])
for plugin in Plugin.__subclasses__():
yield plugin
在Python 2.7或3.1+中,考虑:
而不是__import__(name, None, None, [''])
import importlib # just once
importlib.import_module(name)
这会加载每个插件文件,并为我们提供所有插件。然后,您可以根据需要选择插件,然后使用它们:
from multiprocessing import Process, Pipe
plugins = {}
for plugin in PluginLoader("plugins"):
... #select plugin(s)
if selected:
plugins[plugin.__name__], child = Pipe()
p = Process(target=plugin, args=(child,))
p.start()
...
for plugin in plugins.values():
plugin.put("EventHappened")
...
for plugin in plugins.values():
event = plugin.get(False)
if event:
... #handle event
这是刚开始时想到的。显然,这需要更多的肉体,但它应该是一个良好的工作基础。
答案 1 :(得分:0)
检查yapsy
插件https://github.com/tibonihoo/yapsy。这应该适合你