пространство имен с импортом подмодулей

#python #python-3.x #namespaces #python-import

#python #python-3.x #пространства имен #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() , и vars() вместо globals() , но результат тот же.

Обновить
Из любопытства я также импортировал foobar bar.py и распечатал globals() и 'bar' не был включен. Итак, похоже, что мои модули добавляются только в пространство имен внутри __init__.py файлов?

Комментарии:

1. Имейте в виду, что подмодули по своей сути являются атрибутами своих родительских модулей. Например, concurrent.futures буквально является .futures атрибутом concurrent . В вашем случае foo содержит baz , потому что последнее есть на самом деле foo.baz .

Ответ №1:

Все благодарности @MisterMiyagi в комментариях.

Я только подтвержду это цитатой из официальной документации 5.4.2. Submodules:

Когда подмодуль загружается с использованием любого механизма […] в пространстве имен родительского модуля помещается привязка к объекту подмодуля.

Например, в вашем случае, если в пакете foo есть подмодуль bar , после импорта foo.bar у foo него будет атрибут bar , который привязан к подмодулю foo.bar .