python - 带有子模块导入的命名空间
问题描述
我想使用一个简单的列表理解来设置__all__
我的包中的模块。我注意到,当我从自己的模块之一导入某些内容时,模块名称会添加到命名空间中,而不仅仅是我正在导入的内容。这与导入内置或第三方包时不同。
- foo
- __init__.py
- bar.py
- baz.py
__init__.py
import os as _os
from numpy.random import randint as _randint
import foo.bar as _bar
from foo.baz import foobar
__all__ = [x for x in globals() if not x.startswith('_')]
我预计:
>>> import foo
>>> foo.__all__
['foobar']
但我得到:
>>> import foo
>>> foo.__all__
['bar', 'baz', 'foobar']
我知道我可以扩展我的列表理解__all__
以过滤掉,ModuleType
但我想知道为什么我自己的模块的行为不同。我真的很希望能够像使用其他包一样使用前导下划线来处理这个问题。我也尝试过使用dir()
, locals()
, andvars()
代替,globals()
但结果是一样的。
更新
出于好奇,我也导入foobar
并bar.py
打印了globals()
,'bar'
没有包括在内。那么,我的模块似乎只添加到__init__.py
文件中的命名空间中?
解决方案
@MisterMiyagi 在评论中的所有功劳。
我只会用官方文档5.4.2 中的引用来确认这一点。子模块:
当使用任何机制加载子模块 [...]时,将在父模块的命名空间中放置与子模块对象的绑定。
例如,在您的情况下,如果 packagefoo
有一个 submodule bar
,在 importing 之后foo.bar
,foo
将有一个bar
绑定到 submodule的属性foo.bar
。