В материале "Инструкция from <modulle> import <names>
" рассматривался случай использования конструкции from <module> import *
, когда все объекты модуля импортируются в область видимости вызывающей стороны, за исключением тех, чьи имена начинаются с символа подчеркивания.
Аналогичное утверждение для пакета выглядит следующим образом from <package> import *
. Попробуем сделать импорт всех модулей пакета из примера материала "Инициализация пакета с модулями":
>>> dir() # ['__annotations__', '__builtins__', '__doc__', '__loader__', # '__name__', '__package__', '__spec__'] >>> from pkg import * >>> dir() # ['__annotations__', '__builtins__', '__doc__', '__loader__', # '__name__', '__package__', '__spec__']
По умолчанию инструкция from <package> import *
ничего не импортирует.
Python следует соглашению: если __init__.py
файл в каталоге пакета содержит список с именем __all__
, он считается списком модулей, которые должны быть импортированы при обнаружении инструкции from <package> import *
.
Изменим __init__.py
в каталоге pkg
следующим образом:
__all__ = [ 'mod1', 'mod2' ] var_init = ['one', 'two', 'three']
Попробуем сделать импорт всех модулей пакета pkg
еще раз.
>>> from pkg import * >>> dir() # ['__annotations__', '__builtins__', '__doc__', '__loader__', # '__name__', '__package__', '__spec__', 'mod1', 'mod2'] >>> mod2.bar() # Модуль 2, функция bar() >>> mod1.foo() # Модуль 1, функция foo(), var_init = ['one', 'two', 'three']
Использование конструкции import *
не считается хорошей практикой, как для пакетов, так и для модулей. Переменная __all__
дает некоторый контроль над тем, что происходит, когда указана конструкция import *
.
Кстати, __all__
также может быть определена в модуле и служит той же цели: контролировать то, что импортируется с помощью конструкции import *
.
Изменим mod1.py
следующим образом:
__all__ = ['foo'] def foo(): from pkg import var_init print('Модуль 1, функция foo()) def other(): print('Модуль 1, функция other())
Теперь конструкция from pkg.mod1 import *
будет импортировать только то, что содержится в __all__
:
>>> from pkg.mod1 import * >>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'foo'] >>> foo() # Модуль 1, функция foo() >>> other() # Traceback (most recent call last): # ... # NameError: name 'other' is not defined
Функция foo()
теперь определена в локальном пространстве имен, а функция other()
- нет, потому что не находится в списке __all__
.
Таким образом, переменная __all__
используется как пакетами, так и модулями для управления тем, что импортируется при использовании конструкции import *
. Но поведение по умолчанию отличается:
__all__
не определен, import *
ничего не импортирует.__all__
не определен, import *
импортирует все, кроме имен, начинающихся с символа подчеркивания.