【问题标题】:namespace with submodule imports带有子模块导入的命名空间
【发布时间】:2021-03-20 02:02:31
【问题描述】:

我想使用一个简单的列表理解来为我的包中的模块设置__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()vars() 而不是globals(),但结果是一样的。

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

【问题讨论】:

  • 请记住,子模块本质上是其父模块的属性。例如,concurrent.futures 就是concurrent.futures 属性。在您的情况下,foo 包含 baz,因为后者实际上是 foo.baz

标签: python python-3.x namespaces python-import


【解决方案1】:

cmets 中 @MisterMiyagi 的所有学分。

我只会用官方文档5.4.2. Submodules的引用来确认这一点:

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

例如在您的情况下,如果包foo 有一个子模块bar,在导入foo.bar 后,foo 将有一个属性bar 绑定到子模块foo.bar

【讨论】:

    猜你喜欢
    • 2016-04-27
    • 2012-05-28
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    • 2015-11-21
    • 2021-05-23
    • 2019-03-14
    相关资源
    最近更新 更多