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

2024-05-15 13:17:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我不能让python的相对导入工作。我已经创建了一个简单的例子,说明它不起作用:

目录结构为:

/__init__.py
/start.py
/parent.py
/sub/__init__.py
/sub/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

我正在使用Python2.6。为什么是这个案子?如何使这个沙盒示例工作?


Tags: 文件infrompyimport目录initline
3条回答

如果要直接调用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]指的是运行入口点的路径。

在python3中查看:

python -V
Python 3.6.5

示例1:

.
├── 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

示例2:

.
├── 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

您正在从包“sub”导入。start.py本身不在包中,即使存在__init__.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

相关问题 更多 >