我对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
Run Code Online (Sandbox Code Playgroud)
(我可以想象在依赖关系上有一个拓扑排序算法来决定插件初始化的顺序.)
我想实现多线程,这意味着每个插件都在自己的线程中运行,该线程有一个可以串行执行的函数调用工作队列.当一个插件调用另一个插件的函数时,它会调用管理器,而管理器又会将函数调用插入到另一个插件的队列中.
此外,管理者应该提供某种事件系统,其中插件可以注册他们自己的事件并成为其他人的事件的听众.
此外,我希望能够在代码更改或其线程崩溃时重新加载插件,而无需关闭管理器/应用程序.我已经阅读了如何卸载(重新加载)Python模块?与此同时.
再次说清楚:管理员不应该提供任何其他功能,而不是支持其插件与彼此之间的通用通信接口,并行运行的能力(以多线程方式,而不需要插件知道这一点)并恢复更新/崩溃的插件.
所以我的问题是:是否可以在python中执行此操作?如果是,那么粗略草图中是否存在设计错误?我很感激对此有任何好的建议.
其他"文献": 用Python实现插件系统
在最基本的层面上,首先,您需要提供一个基本的插件类,它是为您的应用程序编写的所有插件的基础.
接下来我们需要全部导入它们.
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
Run Code Online (Sandbox Code Playgroud)
在Python 2.7或3.1+中__import__(name, None, None, ['']),考虑:
import importlib # just once
importlib.import_module(name)
Run Code Online (Sandbox Code Playgroud)
这会加载每个插件文件并为我们提供所有插件.然后,您可以根据需要选择插件,然后使用它们:
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
Run Code Online (Sandbox Code Playgroud)
这是刚开始时想到的.显然,这需要更多的肉体,但它应该是一个良好的工作基础.