Что происходит, когда Python импортирует собственный модуль?

Когда Python импортирует модуль:
  1. Поиск модуля: Python ищет файл модуля в списке путей поиска (sys.path).
  2. Компиляция: Если найденный файл имеет расширение .py, он компилируется в байт-код (.pyc или .pyo) при первом импорте или если исходный файл новее, чем байт-код.
  3. Выполнение: Python выполняет байт-код модуля.
  4. Создание объекта модуля: Создается объект модуля в текущем пространстве имен.
  5. Присваивание имени: Имя модуля присваивается объекту модуля, делая его доступным через имя импорта.
Важно: Модуль импортируется только один раз за сессию. Последующие импорты возвращают ссылку на уже импортированный объект.

Когда Python импортирует собственный модуль, происходит следующая последовательность действий:
  1. Поиск модуля: Python ищет модуль в определенном порядке, используя список путей поиска, хранящийся в переменной sys.path. Этот список обычно включает:
    • Текущий каталог скрипта, из которого выполняется импорт.
    • Каталоги, указанные в переменной окружения PYTHONPATH (если она задана).
    • Каталоги установки Python по умолчанию.
  2. Поиск файла: Python пытается найти файл с именем модуля и расширением .py, .pyc (скомпилированный байт-код), .pyo (оптимизированный байт-код) или другие расширения, соответствующие модулям расширения (например, .so или .dll). Если модуль является пакетом, он ищет подкаталог с именем модуля и файлом __init__.py внутри него.
  3. Компиляция (если необходимо): Если найден только исходный файл .py, Python компилирует его в байт-код, создавая файл .pyc (или .pyo, если используется опция -O или -OO). Этот процесс оптимизирован: если .pyc файл уже существует и он новее, чем .py файл, то компиляция пропускается.
  4. Выполнение кода модуля: Python выполняет байт-код модуля. Все определения функций, классов и переменных, находящиеся на верхнем уровне модуля, выполняются и добавляются в пространство имен модуля.
  5. Кэширование модуля: Создается объект модуля, который сохраняется в sys.modules - словаре, хранящем все импортированные модули. Это делается для предотвращения повторной загрузки и выполнения одного и того же модуля при последующих импортах. Если модуль уже есть в sys.modules, Python просто возвращает ссылку на существующий объект модуля, не выполняя поиск, компиляцию и выполнение заново.
  6. Предоставление доступа: Импортирующий модуль получает доступ к содержимому импортированного модуля через имя модуля (если используется import module_name) или через имена, явно импортированные с помощью from module_name import name1, name2.

Важные моменты:

  • sys.modules - это глобальный словарь, который позволяет Python отслеживать уже импортированные модули и предотвращать повторную загрузку.
  • Модули выполняются только один раз, даже если импортируются несколько раз. Последующие импорты просто возвращают ссылку на уже загруженный модуль.
  • Порядок путей поиска в sys.path важен, так как Python ищет модуль в этих каталогах последовательно.
  • Можно перезагрузить модуль с помощью importlib.reload(module), но это обычно не рекомендуется, так как может привести к непредсказуемому поведению, особенно если модуль используется в других частях программы.
  • Использование __init__.py позволяет Python рассматривать каталог как пакет, содержащий модули и подпакеты.
0