强制从当前目录导入模块

36

我有一个名为p的包,它包含模块aba依赖于b

b.py的内容:

import a

然而我希望 确保 b 从同一 p 包目录下导入我的 a 模块,而不仅仅是从 PYTHONPATH 中导入任何一个 a 模块。

因此,我尝试将 b.py 更改如下:

from . import a

只要我在p包目录之外导入b,这就有效。 给定以下文件:

/tmp
    /p
       a.py
       b.py
       __init__.py
以下内容是有效的:
$ cd /tmp
$ echo 'import p.b' | python

以下方法是无效的:

$ cd /tmp/p
$ echo 'import b' | python
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "b.py", line 1, in <module>
    from . import a
ValueError: Attempted relative import in non-package

为什么?

P.S. 我正在使用 Python 2.7.3。

3个回答

18

在重新阅读了Python导入文档之后,我原来问题的正确答案是:

为确保b从自己的包中导入a,只需要在b中编写以下内容:

import a

这是文档中的引用:

子模块经常需要相互引用。例如,surround模块可能会使用echo模块。事实上,这种引用非常普遍,以至于导入语句首先在包含包中查找,然后再在标准模块搜索路径中查找。

注意: 如下评论区J.F. Sebastian所建议的一样,不建议使用隐式导入,在Python 3中已经被删除。


10
不要使用隐式相对导入(在Python 3中已经取消)。始终使用绝对导入(from p import a(如果存在p/p.py文件,则在其前面添加from __future__ import absolute_import))或显式相对导入(from . import a(如果不是__main__模块))。不要从Python包目录内运行脚本;这会将该目录前缀添加到sys.path中,可能导致同一模块的不同名称可用,从而导致与模块级状态相关的错误(如果使用隐式相对导入,则还会遮盖其他顶级模块)。 - jfs

7
因为在 /p 中有一个 __init__.py 文件。这个文件告诉 Python:“这个文件夹中的所有模块都属于包 p”。
只要存在 __init__.py 文件,无论你在哪里,都可以将 b 导入为 p.b
所以,在 b.py 中正确的导入方式是:import p.a

哪个版本的Python?这种行为在过去发生了变化。 - Aaron Digulla
按照您的建议更改了 b.py。现在运行 import b 会出现 ImportError: No module named p.a 错误。Python 2.7.3。 - Zaar Hai
在这种情况下,您永远不应该使用import b。始终使用import p.b或从__init__.py中使必要的符号可用,并使用import p来隐藏内部细节。 - Aaron Digulla
你的问题在于混合使用(旧式)相对导入和新的基于包的导入。旧式导入方式不稳定,这就是为什么引入了新风格导入的原因。请参阅 http://docs.python.org/2/tutorial/modules.html#packages 中的“包”部分。 - Aaron Digulla
1
那么完成我的任务的正确方法是什么?在 b.py 中导入 p.a 吗?这样做可以工作,但如果我将来想要将 p 重命名为其他名称,我就必须更改很多文件... - Zaar Hai

0

相对导入仅限于包内使用。

如果您从当前位置导入b,则不存在包的概念,因此无法进行相对导入。

如果您导入p.b,那么它是包c中的模块b

重要的不是目录结构,而是包的结构。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接