使用自定义设置导入Python包

时间:2014-08-15 06:51:17

标签: python python-2.7 python-3.x plugins

我正在开发一个简单的字典工具,其基类可以通过插件扩展来表示不同的字典。插件在文件系统中组织如下:

plugins/
├── dict1
│   ├── ...
│   ├── settings.py
│   └── dict1.py
└── dict2
    ├── ...
    ├── settings.py
    └── dict2.py

主应用程序发现并加载这样的插件:

import os

PLUGINS_DIR = 'plugins'
PLUGINS_PATH = os.path.join(os.path.dirname(__file__), PLUGINS_DIR)


def discover_dictionaries():
    for plugin_name in os.listdir(PLUGINS_PATH):
        plugin_path = os.path.join(PLUGINS_PATH, plugin_name, plugin_name + '.py')
        if os.path.isfile(plugin_path):
            name = '.'.join([PLUGINS_DIR, plugin_name, plugin_name])
            module = __import__(name, fromlist=['Dictionary'])
            yield plugin_name, getattr(module, 'Dictionary')()

如上文在文件系统布局中所示,大多数插件在同一目录中都有一个settings.py文件,其中包含插件的自定义设置。插件的主程序包导入如下设置:

from settings import dictionary_path

这在Python 2.7中运行良好。但是在Python 3中我得到了这个堆栈跟踪:

Error: could not import Dictionary from /tmp/webdict/plugins/wud/wud.py
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "<string>", line 1, in <listcomp>
  File "/tmp/webdict/util.py", line 14, in discover_dictionaries
    module = __import__(name, fromlist=['Dictionary'])
  File "/tmp/webdict/plugins/wud/wud.py", line 4, in <module>
    from settings import dictionary_path
ImportError: No module named 'settings'

settings.py文件位于/tmp/webdict/plugins/wud/settings.py,程序适用于Python 2但不适用于Python 3.在运行Python 3之前,我用以下内容擦除了所有*.pyc文件: / p>

find plugins -name '*.pyc' -delete

完整的项目是GitHub上的开源项目。

重现问题:

# clone test1 branch
git clone -b test1 https://github.com/janosgyerik/webdict

# raises ImportError -> what I want to fix
python3.4 -c 'import util; print([x for x in util.discover_dictionaries()])'

# NO ImportError -> GOOD (the IOError doesn't matter for this test)
python2.6 -c 'import util; print([x for x in util.discover_dictionaries()])'

换句话说,在Python 2中,插件对from settings import blah没有问题,在自己的目录中有settings.py,但这在Python 3中不起作用。我应该怎么做? / p>

我对discover_dictionaries方法也不是很满意。可能它可以做得更好,但我不知道如何。请指教!

1 个答案:

答案 0 :(得分:1)

对于Python 3,您需要使用相对导入:from .settings import dictionary_path

否则,它会在settings上的某个地方寻找sys.path

为了保持一致性,您可以使用from __future__ import absolute_import

在Python 2中获得此行为