我正在开发一个简单的字典工具,其基类可以通过插件扩展来表示不同的字典。插件在文件系统中组织如下:
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
方法也不是很满意。可能它可以做得更好,但我不知道如何。请指教!
答案 0 :(得分:1)
对于Python 3,您需要使用相对导入:from .settings import dictionary_path
。
否则,它会在settings
上的某个地方寻找sys.path
。
为了保持一致性,您可以使用from __future__ import absolute_import