Python3插件系统

时间:2011-12-19 20:54:26

标签: python plugin-architecture

我正在尝试创建一个类似于yapsy的插件框架(不幸的是yapsy不兼容python3)。

我的代码如下所示:

root
   main.py
   plugins/
       __init__.py
       PluginManager.py
       UI/
           __init__.py
           textui.py

在PluginManager.py中我定义了以下类:

class PluginMetaclass(type):
    def __init__(cls, name, base, attrs):
        if not hasattr(cls, 'registered'):
            cls.registered = []
        else:
            cls.registered.append((name,cls))

class UI_Plugins(object):
    __metaclass__ = PluginMetaclass

    #...some code here....

    def load():
         #...some code here too...

        if "__init__" in  os.path.basename(candidate_filepath):
            sys.path.append(plugin_info['path'])
        try:
            candidateMainFile = open(candidate_filepath+".py","r")  
            exec(candidateMainFile,candidate_globals)
        except Exception as e:
            logging.error("Unable to execute the code in plugin: %s" % candidate_filepath)
            logging.error("\t The following problem occured: %s %s " % (os.linesep, e))
            if "__init__" in  os.path.basename(candidate_filepath):
                sys.path.remove(plugin_info['path'])
            continue

其中candidate_filepath包含插件路径。

textui.py包含以下内容:

from root.plugins.PluginManager import UI_Plugins

class TextBackend(UI_Plugins):
    def run(self):
        print("c")

当我尝试加载插件时,我收到此错误:

No module named plugins.PluginManager 

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:5)

很抱歉,这肯定不是你问题的直接答案,但是如果你正在尝试为python3开发非常接近yapsy的东西,那么你可能会对我发布了一对的yapsy的新版本感兴趣兼容python3的软件包:

https://sourceforge.net/projects/yapsy/files/Yapsy-1.9/

(见Yapsy-1.9_python3-py3.2.egg或Yapsy-1.9-python3.tar.gz)

源代码位于特定分支上:

http://yapsy.hg.sourceforge.net/hgweb/yapsy/yapsy/file/91ea058181ee

答案 1 :(得分:2)

导入声明

from root.plugins.PluginManager import UI_Plugins

不起作用,因为root不是包。

但是,如果应用程序以

启动
python3 root/main.py

然后root实际上不需要成为一个包。

您需要做的就是将textui.py中的import语句更改为

from plugins.PluginManager import UI_Plugins

并且应该正常工作。

这样做的原因是因为当前运行的脚本的目录总是自动添加到sys.path的开头。在您的情况下,这将是root,并且由于plugins是该目录中的包,因此可以从应用程序中的任何位置直接导入。因此,只要您的main脚本保持原样,就不需要任何其他路径操作。

答案 2 :(得分:1)

  1. 要获得包,您需要在目录中有一个__init__.py文件。它可能是空的,但它必须存在于“root”和“plugin”目录中。
  2. 目录的名称是命名空间的名称,因此它们必须仔细匹配。在您的情况下,您需要使用from root.plugin.PluginManager import UI_Plugins
  3. 最后,为了导入工作,包必须在您的PYTHONPATH中(参见语言文档中的The Module Search Path)。您可以通过将目录添加到sys.path列表中,将代码添加到PYTHONPATH环境变量中来实现此目的。