Python 2.7和3.4之间包导入的区别

20

对于这个目录层次结构:

.
├── hello
│   ├── __init__.py
│   └── world
│       └── __init__.py
└── test.py

而且,Python源文件:

test.py:

if __name__ == '__main__':
    import hello

你好/__init__.py:

import world

你好/世界/__init__.py:

print("yes you win")

使用Python 3.4运行test.py时,会抛出ImportError错误,提示找不到模块world,但使用Python 2.7则一切正常。

我知道在搜索导入的模块时会引用sys.path,所以将目录hello添加到sys.path中可以消除这个错误。

但在Python 2.7中,在导入world之前,目录hello也不在sys.path中。是什么原因导致了这种差异?在Python 2.7中是否应用了递归搜索策略?


2
请参阅PEP 328。 - user2357112
1个回答

16

Python 3使用绝对导入(参见@user2357112提到的PEP 328)。简而言之,Python 3从每个sys.path条目的根目录开始搜索,而不是像在sys.path中加入模块所在目录一样首先查询模块目录。

要获得您想要的行为,您可以采用以下方法:

  • 显式使用相对导入:在hello包中使用from . import world
  • 使用绝对导入:import hello.world

是的,我已经阅读了 PEP。我在 Python 2.7 的文档中阅读了有关模块搜索路径的内容(此处)。在我的示例中,运行 test.py 将添加点 (.) 目录到 sys.path,但不会添加包含 world 的目录,那么 Python 2.7 解释器如何找到包 world 呢? - pjhades
world 是一个。Python 将包目录 world 与同一目录中的模块 world.py 视为相同(至少在我们这里是这样)。__init__.py内部 加载的事实对此无关紧要。这有意义吗? - Sean Vieira
是的,它有帮助。也许最好的方法是阅读代码。谢谢 :) - pjhades
1
“import .world” 在 Python 3 中是否是有效的语法?我认为你应该使用 “from . import world”。 - pevogam

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