python - 模块的导入顺序

python - order of import for modules

例如有一些文件夹:

.
├── file_a.py
├── file_b
│   └── __init__.py
└── file_b.py

其中 file_a.py 类似于:

from file_b import some_function

我知道这绝对不是一个好的做法,但后面的解析顺序是什么?

即python 如何决定为 "absolute import" 导入哪个模块?

我做了个小实验,做了somelib.pysomelib/__init__.py 然后尝试了以下

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

显然 python 更喜欢 directory-based 模块而不是 file-based 模块

正如@scnerd 指出的那样,这可能是意外行为,但这是我在默认实现中看到的。

如果您想知道这是怎么发生的,您可能会查看 importlib 以了解可怕的细节

我不确定此信息在文档中的位置(或是否)- 在 import system docs didn't turn it up - but PEP 420 中快速检查说明如下:

While looking for a module or package named "foo", for each directory in the parent path:

  • If <directory>/foo/__init__.py is found, a regular package is imported and returned.
  • If not, but <directory>/foo.{py,pyc,so,pyd} is found, a module is imported and returned. The exact list of extension varies by platform and whether the -O flag is specified. The list here is representative.
  • If not, but <directory>/foo is found and is a directory, it is recorded and the scan continues with the next directory in the parent path.
  • Otherwise the scan continues with the next directory in the parent path.

If the scan completes without returning a module or package, and at least one directory was recorded, then a namespace package is created.

所以根据 PEP 420,如果在同一个目录中找到同名的包和 non-package 模块,则包胜出。

根据@JonKiparsky 的建议,我仔细研究了 importlib,最终找到了 importlib._bootstrap.FileFinder.find_spec,它确实在查找符合包名称的有效文件之前明确检查目录。不过,很高兴看到 @user2357112 的回答,这应该是定义的行为,而不仅仅是偶然事件。