Python3导入问题

时间:2016-08-18 08:13:56

标签: python python-3.x import

这个问题被多次询问,但在我的案例中,没有一个解决方案似乎有所帮助。

我有一个像这样的目录结构

my_project/
    main.py
    bootstrap/
        __init__.py
        boot.py
    consumer/
        __init__.py
        main.py

位于顶层目录(myproject)并执行python3 consumer/main.py会引发错误:

Traceback (most recent call last):
  File "consumer/main.py", line 7, in <module>
    from bootstrap.boot import MyClass
ImportError: No module named 'bootstrap'

奇怪的是,使用解释器导入该模块按预期工作。从PyCharm运行代码也可以正常工作。

我尝试使用“完整路径”导入,例如from my_project.bootstrap.boot import MyClass失败的ImportError失败。我也试过使用相对导入,例如from .bootstrap.boot import MyClass {/ 1}}也失败了SystemError: Parent module '' not loaded, cannot perform relative import

修复此问题的一个方法就是我在virtualenv export PYTHONPATH="/root/my_project"脚本底部添加activate

1 个答案:

答案 0 :(得分:4)

您收到此错误,因为模块搜索路径仅包含当前目录,而不包括其父目录;由于您的其他模块不在PYTHONPATH中,因此无法导入。

您可以在脚本中打印sys.path来自行查找。

我使用以下内容创建了一个目录t

$ tree
.
├── a.py
├── bar
│   ├── __init__.py
│   └── world.py
└── foo
    ├── hello.py
    └── __init__.py

2 directories, 5 files

以下是hello.py的来源:

$ cat foo/hello.py
import sys
print("I am in {}".format(__file__))
for path in sys.path:
    print(path)

from bar.world import var
print(var)

现在看一下当我执行foo/hello.py并尝试从bar/world.py导入内容时会发生什么;

$ python foo/hello.py
I am in foo/hello.py
/home/burhan/t/foo
/usr/lib/python2.7
/usr/lib/python2.7/plat-x86_64-linux-gnu
/usr/lib/python2.7/lib-tk
/usr/lib/python2.7/lib-old
/usr/lib/python2.7/lib-dynload
/home/burhan/.local/lib/python2.7/site-packages
/usr/local/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages
Traceback (most recent call last):
  File "foo/hello.py", line 6, in <module>
    from bar.world import var
ImportError: No module named bar.world

从打印的路径可以看出,只列出了系统范围的Python库路径以及脚本的当前目录。这就是找不到bar.world的原因。

要解决此问题,您可以调整PYTHONPATH或使用相对导入;例如:

$ PYTHONPATH=../t python foo/hello.py
I am in foo/hello.py
/home/burhan/t/foo
/home/burhan/t
/usr/lib/python2.7
/usr/lib/python2.7/plat-x86_64-linux-gnu
/usr/lib/python2.7/lib-tk
/usr/lib/python2.7/lib-old
/usr/lib/python2.7/lib-dynload
/home/burhan/.local/lib/python2.7/site-packages
/usr/local/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages
42

您注意到我在这里手动覆盖PYTHONTPATH并添加脚本的公共父级(42来自bar / world)。

要使用相对导入修复此问题,首先要在最顶层的目录中创建一个包,否则您将收到着名的Attempted relative import in non-package错误;有关这方面的更多信息以及有关Python 3导入如何工作的详细信息,请查看:Relative imports in Python 3