Python - 模块导入的顺序

6
举个例子,这里有一个文件夹:
.
├── file_a.py
├── file_b
│   └── __init__.py
└── file_b.py

file_a.py 中有类似以下内容时:

from file_b import some_function

我知道这绝对不是一个好的实践方法,但是背后的解析顺序是什么?

也就是说,Python如何决定导入哪个模块进行“绝对导入”?


Python的路径? - Mad Physicist
3个回答

5
我不确定这个信息在文档中是否存在,但是在import system docs进行了快速检查,没有找到。然而,根据PEP 420的说法:
当寻找名为“foo”的模块或包时,在父路径中的每个目录中进行以下操作:
- 如果找到/foo/__init__.py,则导入常规包并返回。 - 如果没有找到,则导入模块并返回/foo.{py,pyc,so,pyd},扩展名的确切列表因平台和-O标志的指定而异。此处列出的列表是代表性的。 - 如果没找到,但是找到了/foo,并且它是一个目录,则将其记录下来,并继续对父路径中的下一个目录进行扫描。 - 否则,继续对父路径中的下一个目录进行扫描。
如果扫描完成后没有返回模块或包,并且至少记录了一个目录,则创建命名空间包。
因此,根据PEP 420的说法,如果在同一目录中发现了一个包和一个非包模块具有相同的名称,则包获胜。

2

根据@JonKiparsky的建议,我在importlib中进行了一些搜索,并最终找到了importlib._bootstrap.FileFinder.find_spec,它确实明确检查目录,然后再寻找符合包名称的有效文件。很高兴看到@user2357112的答案,这应该是定义行为,而不仅仅是偶然事件。


1

我做了一个小实验,创建了somelib.pysomelib/__init__.py文件。 然后尝试了以下操作。

>>> from somelib import foo
in somelib/__init__.py
>>>

显然,Python更喜欢基于目录的模块而不是基于文件的模块。正如@scnerd所指出的那样,这可能是偶然行为,但这是我在默认实现中看到的。如果你想知道这是如何发生的,你可能会查阅importlib了解可怕的细节。

2
我找不到“正确答案”的任何定义......虽然这似乎完全有可能Pypy、Jython、IronPython等可能会偶然地以不同的方式执行。 - scnerd

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