【问题标题】:How to provide an API to extend a Python program with plugins?如何提供 API 来使用插件扩展 Python 程序?
【发布时间】:2011-07-04 18:11:19
【问题描述】:

我想知道如何为我的 Python 程序提供一个 API,以使其他人能够使用插件对其进行扩展。 我想到了类似from myProgram.plugins import aClassToExtendByOthers, registerThatClass 的东西。 但我不知道如何提供这个。

我可以在我的 loadPlugins 函数中为插件文件夹中的每个插件使用一个 exec 语句,但这不会启用导入我想要的东西 供人们编写这些插件。

【问题讨论】:

  • 这里是several ways,用于在 Python 中实现命令调度模式。

标签: python api plugins extend


【解决方案1】:

对于我在几个程序中使用的系统,我定义了一个插件目录,并为所有插件提供了一个基础插件类以进行子类化。然后我导入目录中的所有模块,并有选择地初始化(通过检查它们是否是我的基本插件类的子类),并将插件实例存储在字典(或列表)中。我发现command dispatch pattern 作为构建插件和传递事件的一种方式对我来说非常有效。基础插件(或另一个可选的接口类)可以提供插件与应用程序交互所需的方法。我希望这有帮助。这可能不是最好的方法,但它对我有用。

此外,您可以进行额外的过滤,例如要求插件文件具有前缀(例如__plug_file.py____plug_other.py__)。

【讨论】:

  • 所以您只是使用了 exec 语句还是我理解错了?
  • 不,我使用 __import__ 函数导入模块,然后使用检查列出我刚刚导入的模块中的所有类。该系统确实允许插件使用其他模块,您说这是您关心的问题之一。在这些情况下只使用 exec 可能很危险。
  • 嗯,这确实比 exec 好。但是我如何提供插件作者可以通过导入它们来使用我为他提供的类? (正如问题中所说的那样,from myProgram.plugins import extensiblePluginClass
  • 是的,只需使用基类制作一些文件并将其导入主程序和每个插件文件中。我这样做的方式是,我通过存在一个名为 __plug__.py 的文件来确定插件目录是否有效,该文件具有必要的类。或者,您可以只在包中的文件中定义类,然后从中导入。之所以把文件放在目录下,是因为我的系统多用,不想手动修改系统的源代码。
【解决方案2】:

您可以使用 imp 模块(请参阅 docs.python.org)

sys.path.insert(0, pluginsDir)
lst = map(lambda x: os.path.splitext(os.path.basename(x))[0], glob.glob(os.path.join(pluginsDir, "*.py")))
for module in lst:
try:
  f, fn, d = imp.find_module(module,[pluginsDir])
  loaded = imp.load_module(module, f, fn, d)

完整功能的例子见 ojuba 控制中心的加载器

http://git.ojuba.org/cgit/occ/tree/OjubaControlCenter/loader.py

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-16
    • 2016-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多