Глобальный импорт модулей в Python

Как сделать так, чтобы модули, импортированные в «базовом» модуле, были доступны модулям, импортирующим этот «базовый» модуль?

Пример.
#parent.py
import _mysql
class Parent:
    pass
#child.py
import parent
class Child(Parent):
    db = _mysql.connect(...

Вызовет ошибку, так как _mysql не находится в глобальной области видимости.

Можно написать
#parent.py
__all__ = ['_mysql']
и сделать
#child.py
from parent import *
Но насколько я понял, это не самый красивый вариант.

Существует ли реализация, при которой не нужно в «дочерних» модулях заново производить импорт общеупотребимых библиотек, которые «не засоряют» глобальную область?
Или повторный импорт — правильное решение?
Как правильно построить иерархию модулей при наследуемых классах?
  • Вопрос задан
  • 4932 просмотра
Решения вопроса 1
@MikhailEdoshin
from parent import _mysql. Можно также просто повторно импортировать _mysql, это вернет уже импортированный модуль из sys.modules. В Python у каждого модуля свое пространство имен, модули между собой никак не пересекаются, и это считается feature, а не bug. Импортировать _mysql даже правильнее, если родительский модуль ничего к нему не добавляет — это явно дает понять, что мы имеем дело с общим _mysql, а не с тем, что в родительском модуле называется _mysql.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@niko83
1. При повторном импорте модуль достаётся из кеша, это не настолько затратно как может показаться.
2. Явное лучше неявного. Гораздо лучше когда в файле сразу видно откуда берётся переменная, а не искать каким магическим образом откуда-то что-то появилось.
Ответ написан
nochkin
@nochkin
#child.py
import parent
db = parent._mysql.connect(…
Ответ написан
Названия, начинающиеся с _ считаются приватными. Они не импортируются, когда вы пишите from module import *. Это продуманная и специально сделанная фича. Так что решение очевидно: не надо давать не приватным модулям имена, начинающиеся с _. Если имя модуля поменять нельзя, то в parent.py надо писать:
import _mysql as mysql

Тогда не надо будет писать
__all__ = ['_mysql']
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы