为什么即使没有显式导入子模块名称也可以在 __init__.py 中访问?

Why can sub-module names be accessed in __init__.py even without explicitly importing them?

问题:

pkg/
    __init__.py
    sub1.py
    sub2.py


$ cat pkg/__init__.py
from .sub2 import *
print("init", dir())

$ cat pkg/sub1.py
from .sub2 import *
print("sub1", dir())

$ cat pkg/sub2.py
def spam():
    ...

$ python -c "import pkg"
init [... 'spam', 'sub2']

$ python -c "import pkg.sub1"
init [... 'spam', 'sub2']
sub1 [... 'spam']

请注意 sub2 是如何在 pkg 的命名空间中的,尽管我实际上并没有导入它。我希望只导入 sub2 中的名称。为什么不是这样呢?我看到它与导入包和导入模块有关,因为:

$ python -c "import pkg.__init__"
init [... 'spam', 'sub2']
init [... 'spam']

好像也很迷惑mypy;我编辑 __init__.py 以显式访问 sub2:

$ cat pkg/__init__.py
from .sub2 import *
print(sub2)

然后 运行 mypy pkg 给出:

pkg/__init__.py:2: error: Name "sub2" is not defined
Found 1 error in 1 file (checked 3 source files)

为什么会这样?这是记录的功能吗?我应该注意到这个“特性”在 Cpython 源代码中使用;例如,检查 Lib/asyncio/__init__.py.

这有点像子模块的怪癖,但这是documented behavior:

When a submodule is loaded using any mechanism (e.g. importlib APIs, the import or import-from statements, or built-in __import__()) a binding is placed in the parent module’s namespace to the submodule object. For example, if package spam has a submodule foo, after importing spam.foo, spam will have an attribute foo which is bound to the submodule.

...

Given Python’s familiar name binding rules this might seem surprising, but it’s actually a fundamental feature of the import system. The invariant holding is that if you have sys.modules['spam'] and sys.modules['spam.foo'] (as you would after the above import), the latter must appear as the foo attribute of the former.