python - 导入父目录问题

时间:2015-04-22 18:33:00

标签: python

我使用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?

3 个答案:

答案 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

绝对导入,意思是

  1. 转到sys.path
  2. 来自其中列出的任何路径
  3. 找到第一个有app模块的人。
  4. 然后从util模块中导入app模块。
  5. ...
  6. 棘手的一点是sys.pathdocumented

      

    在程序启动时初始化时,此列表的第一项path [0]是包含用于调用Python解释器的脚本的目录。如果脚本目录不可用(例如,如果以交互方式调用解释器或者从标准输入读取脚本),path [0]是空字符串,它指示Python首先搜索当前目录中的模块。请注意,在作为PYTHONPATH结果插入的条目之前插入了脚本目录。

    因此,如果您运行Foo/app/tests/test_gram.pysys.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