有人能解释一下 Python 的相对导入吗?

我无论如何都不能让 python 的相对导入工作。我创建了一个简单的例子,说明它在哪些方面不起作用:

目录结构是:

__init__.py
start.py
parent.py
sub/
__init__.py
relative.py

/start.py只包含: import sub.relative

/sub/relative.py只包含 from .. import parent

其他文件都是空白的。

在命令行上执行以下命令时:

$ cd /
$ python start.py

我得到了:

Traceback (most recent call last):
File "start.py", line 1, in <module>
import sub.relative
File "/home/cvondrick/sandbox/sub/relative.py", line 1, in <module>
from .. import parent
ValueError: Attempted relative import beyond toplevel package

我正在使用 Python 2.6。为什么是这种情况? 我如何使这个沙盒示例工作?

114273 次浏览

您是从包“子”导入。即使有一个 __init__.py目前的 start.py本身不在一个包。

您需要从 parent.py上的一个目录启动程序:

./start.py


./pkg/__init__.py
./pkg/parent.py
./pkg/sub/__init__.py
./pkg/sub/relative.py

start.py:

import pkg.sub.relative

现在 pkg 是顶级软件包,您的相对导入应该可以工作。


如果你想坚持你当前的布局,你可以只使用 import parent。因为使用 start.py启动解释器,所以 start.py所在的目录位于 python 路径中。parent.py作为一个独立的模块生活在那里。

如果没有将任何内容导入到目录树上方的脚本中,也可以安全地删除顶级 __init__.py

如果您要直接调用 relative.py,也就是说,如果您真的想从一个顶级模块导入,您必须显式地将它添加到 sys.path列表中。
它应该是这样运作的:

# Add this line to the beginning of relative.py file
import sys
sys.path.append('..')


# Now you can do imports from one directory top cause it is in the sys.path
import parent


# And even like this:
from parent import Parent

如果你认为上述内容会导致某种不一致,你可以使用以下方法:

sys.path.append(sys.path[0] + "/..")

sys.path[0]指入口点运行的路径。

看看巨蟒3:

python -V
Python 3.6.5

例子一:

.
├── parent.py
├── start.py
└── sub
└── relative.py


- start.py
import sub.relative


- parent.py
print('Hello from parent.py')


- sub/relative.py
from .. import parent

如果我们像这样运行它(只是为了确保 PYTHONPATH 是空的) :

PYTHONPATH='' python3 start.py

产出:

Traceback (most recent call last):
File "start.py", line 1, in <module>
import sub.relative
File "/python-import-examples/so-example-v1/sub/relative.py", line 1, in <module>
from .. import parent
ValueError: attempted relative import beyond top-level package

如果我们在 sub/relative.py中更改导入

- sub/relative.py
import parent

如果我们这样运行:

PYTHONPATH='' python3 start.py

产出:

Hello from parent.py

例子二:

.
├── parent.py
└── sub
├── relative.py
└── start.py


- parent.py
print('Hello from parent.py')


- sub/relative.py
print('Hello from relative.py')


- sub/start.py
import relative
from .. import parent

就像这样:

PYTHONPATH='' python3 sub/start.py

产出:

Hello from relative.py
Traceback (most recent call last):
File "sub/start.py", line 2, in <module>
from .. import parent
ValueError: attempted relative import beyond top-level package

如果我们在 sub/start.py中更改导入:

- sub/start.py
import relative
import parent

就像这样:

PYTHONPATH='' python3 sub/start.py

产出:

Hello from relative.py
Traceback (most recent call last):
File "sub/start.py", line 3, in <module>
import parent
ModuleNotFoundError: No module named 'parent'

就像这样:

PYTHONPATH='.' python3 sub/start.py

产出:

Hello from relative.py
Hello from parent.py

此外,最好使用从根文件夹导入,例如:

- sub/start.py
import sub.relative
import parent

就像这样:

PYTHONPATH='.' python3 sub/start.py

产出:

Hello from relative.py
Hello from parent.py