Когда модуль импортируется с разных точек входа в программе, Python ведет себя достаточно умно, чтобы не загружать и не исполнять его несколько раз.
Процесс импорта:
- Когда Python встречает оператор `import`, он сначала проверяет, был ли модуль уже импортирован ранее в течение текущего сеанса работы интерпретатора. Эта информация хранится в словаре `sys.modules`.
- Если модуль уже есть в `sys.modules`, Python просто использует уже загруженный объект модуля. Никакой повторной загрузки и инициализации не происходит. Это означает, что все переменные, функции и классы, определенные в модуле, будут общими для всех частей программы, которые его импортируют.
- Если модуля нет в `sys.modules`, Python выполняет следующие шаги:
- Находит файл модуля (обычно `.py` файл) используя `sys.path` (список директорий, где Python ищет модули).
- Читает и компилирует код модуля.
- Создает новый объект модуля.
- Исполняет код модуля (выполняются все верхнеуровневые операторы, определяются функции, классы, присваиваются значения переменным).
- Добавляет объект модуля в `sys.modules`.
Ключевые моменты:
- Единожды загружен: Модуль загружается и исполняется только один раз за сеанс работы интерпретатора, независимо от того, сколько раз он импортируется.
- Состояние модуля: Любые изменения, внесенные в состояние модуля (например, изменение значения глобальной переменной) одной частью программы, будут видны всем остальным частям программы, которые импортируют этот модуль.
- `sys.modules`: Этот словарь является ключевым для понимания механизма импорта. Вы можете использовать его для проверки, был ли модуль уже загружен, и даже для ручного манипулирования импортом (хотя это обычно не рекомендуется).
- Побочные эффекты: Поскольку код модуля выполняется только один раз, любые побочные эффекты, возникающие во время импорта (например, создание файлов, подключение к базам данных), также произойдут только один раз.
Пример:
# модуль my_module.py
print("Модуль my_module загружен")
x = 10
# script1.py
import my_module
print("x в script1:", my_module.x)
my_module.x = 20
# script2.py
import my_module
print("x в script2:", my_module.x)
# Вывод:
# Модуль my_module загружен
# x в script1: 10
# x в script2: 20
В этом примере, "Модуль my_module загружен" будет напечатано только один раз. Изменение значения `my_module.x` в `script1.py` отразится на `script2.py`.