首页 > 解决方案 > 带有子模块导入的命名空间

问题描述

我想使用一个简单的列表理解来设置__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()但结果是一样的。

更新
出于好奇,我也导入foobarbar.py打印了globals()'bar'没有包括在内。那么,我的模块似乎只添加到__init__.py文件中的命名空间中?

标签: pythonpython-3.xnamespacespython-import

解决方案


@MisterMiyagi 在评论中的所有功劳。

我只会用官方文档5.4.2 中的引用来确认这一点。子模块

当使用任何机制加载子模块 [...]时,将在父模块的命名空间中放置与子模块对象的绑定

例如,在您的情况下,如果 packagefoo有一个 submodule bar,在 importing 之后foo.barfoo将有一个bar绑定到 submodule的属性foo.bar


推荐阅读