为Python服务实现Home Grown插件

时间:2012-09-09 01:38:16

标签: python plugins importerror

我正在编写一个简单的调度服务。我不想硬编码它可以安排的所有任务,而是希望支持可以放在文件夹中并在运行时动态加载的插件。

我的计划是拥有一个JSON文件(或任何配置文件),它将任务名称映射到Python文件(模块)的位置,该文​​件将具有一个名为Plugin的类。我觉得很简单。当有人安排任务运行时,他们会传递任务名称和运行它的时间。当时间过去之后,插件被加载(或重新加载)并运行传递给调度程序的任何其他参数。

我一直在查看imp模块,了解如何在运行时加载模块。我不确定是否要使用其物理位置(文件系统路径)列出插件,或者使用他们在import语句中看到的模块名称。似乎imp想要使用物理位置。

我有两个不同版本的代码“正常工作”。这是一个使用importlib

的人
    pluginName = self.__pluginLookup[pluginName]
    module = import_module(pluginName)
    module = reload(module)  # force reload

    plugin = module.Plugin()
    return plugin

这是我用imp写的:

    path = self.__pluginLookup[pluginName]
    path, moduleName = split(path)
    moduleName, extension = splitext(moduleName)

    file, path, description = find_module(moduleName, [path])
    with file:
        module = load_module(moduleName, file, path, description)

    plugin = module.Plugin()
    return plugin

我遇到的问题是处理依赖项。如果我的plugin.py文件取决于同一文件夹中的dependency.py文件,则说import dependency似乎不起作用。相反,它会从PYTHONPATH查找依赖项。

如何相对于插件本身进行导入?

2 个答案:

答案 0 :(得分:2)

您可以将path追加到sys.path

import sys
sys.path.append(path)

其中path是包含dependency.py。

的目录

答案 1 :(得分:1)

如果您的plugins目录中包含__init__.py,则可以将该目录添加到sys.path。然后那里的模块可以from . import dependency导入另一个插件。或者,如果插件本身是一个子包(即具有自己的__init__.py的目录),那么它可以from . import dep在同一个插件中导入依赖项,或者from .. import dep导入一个来自全局plugins目录的依赖项。使用此设置,您甚至不需要使用imp等;您可以使用__import__函数,该函数按模块名称工作。

然而,一个可能的皱纹是你说插件目录将“在当前工作目录下”。这究竟是什么意思?您的意思是您希望人们能够在驱动器上的任何位置添加插件并仍然使用它们吗?最好为您的应用设置一个中央插件目录,并将其添加到sys.path,并告诉人们将插件放在那里。