我使用virtualenv创建了一个Foo项目,我在test_file.py中导入了File模块时遇到了一些问题
这是我的项目目录
Foo/
├── app
│ ├── __init__.py
│ ├── testfile.py
│ ├── tests
│ │ ├── __init__.py
│ │ └── test_gram.py
│ ├── util
│ │ ├── File.py
│ │ ├── Gram.py
│ │ ├── __init__.py
└── NOTES
test_gram.py:
from app.util.File import loadDataFromPickle
listofdict = loadDataFromPickle(".....")
i = 0
for item in listofdict[:50]:
print(item)
如果我运行test_gram,我收到一个ImportError:
Traceback (most recent call last):
File "test_gram.py", line 1, in <module>
from app.util.File import loadDataFromPickle
ImportError: No module named 'app
我做错了什么?我是否需要将virtualenv-path更改为Foo / app而不是Foo?
答案 0 :(得分:3)
如果test_gram.py位于tests文件夹中,则导入行应为:
from ..util.File import loadDataFromPickle$
另一种选择是使用imp
模块,这通常是建议的,而不是附加sys.path(source here,包括Python 3版本)
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
答案 1 :(得分:2)
from app.util.File import loadDataFromPickle
是绝对导入,意思是
sys.path
app
模块的人。 util
模块中导入app
模块。棘手的一点是sys.path
,documented为
在程序启动时初始化时,此列表的第一项path [0]是包含用于调用Python解释器的脚本的目录。如果脚本目录不可用(例如,如果以交互方式调用解释器或者从标准输入读取脚本),path [0]是空字符串,它指示Python首先搜索当前目录中的模块。请注意,在作为PYTHONPATH结果插入的条目之前插入了脚本目录。
因此,如果您运行Foo/app/tests/test_gram.py
,sys.path
将以.../Foo/app/tests/
开头。该目录下方的任何位置都没有app
模块,因此您无法使用绝对导入导入app
(除非某些app
位于某个地方sys.path
}})。
正如评论和其他答案中所建议的那样,在这种情况下使用相对导入是一种好习惯:
from ..util.File import loadDataFromPickle
相对导入为relative to the current package/module,而不是sys.path
中的目录。
修改强>
但是,直接从命令行运行脚本时,相对导入将不起作用,因为python会抱怨''
模块尚未导入(Parent module '' not loaded, cannot perform relative importSystemError: Parent module ''
)。好吧,那是因为在直接运行脚本时没有加载父模块(tests
和''
),导入器正确地认为它们应该是。
一招是run the test script as a module:
python -m app.tests.test_gram.py
这很可能需要对测试脚本进行一些更改,至少需要
if __name__ == '__main__':
[...]
在脚本中。有关详细信息,另请参阅Relative imports in Python 3。
作为建议,无论如何,您可能希望将测试脚本转换为使用unittest
。
答案 2 :(得分:0)
您所在的test_gram.py
位于app
的子文件夹中。因此,当您尝试导入app
时,它会在app
中查找tests
,而不是import sys
sys.path.append('/Foo/app/util')
from File import loadDataFromPickle
:
group by group_name