Как работает импорт модулей и что делать с циклическими импортами?
- Что происходит при import в Python?
- Зачем нужен __init__.py?
При первом import модуль ищется по sys.path, выполняется сверху вниз один раз и кладётся в sys.modules; повторные импорты берут его оттуда. Циклический импорт ломается, когда модуль A ещё не дошёл до нужного имени, а B уже пытается его взять — ImportError: cannot import name. Лечат разделением модулей, импортом модуля вместо имени или переносом импорта внутрь функции.
- __init__.py делает папку обычным пакетом и выполняется при его импорте
- Без __init__.py — namespace package (PEP 420)
- Код на уровне модуля выполняется при импорте — не делать там тяжёлых действий
А ещё if TYPE_CHECKING: — импорт только для аннотаций, без цикла во время выполнения
Подробно
Шаги import X:
- проверить
sys.modules— если есть, вернуть; - найти модуль через искатели (
sys.meta_path) поsys.path: папка скрипта, PYTHONPATH, site-packages; - создать объект модуля, положить в
sys.modulesдо выполнения; - выполнить код модуля.
Почему ломается цикл. a.py начинает выполняться, импортирует b; b.py делает from a import helper — a уже в sys.modules, но выполнен только до строки импорта, helper ещё нет.
Решения:
- вынести общее в третий модуль (часто цикл — признак плохого разбиения);
import aи обращениеa.helperпри вызове, а не при импорте;- импорт внутри функции;
- для аннотаций —
from __future__ import annotationsи импорт подif TYPE_CHECKING:.
Абсолютные и относительные: from .models import User — внутри пакета; запуск файла пакета как скрипта ломает относительные импорты — использовать python -m package.module.
Что хотят услышать
- Механика импорта и sys.modules.
- Причина и решения циклических импортов.
- Роль __init__.py.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Модуль выполняется заново при каждом import, поэтому глобальные объекты в нём не общие
- ✗Циклический импорт невозможен — Python запрещает его при компиляции
- ✓Модуль выполняется один раз и кэшируется в sys.modules; циклы лечат разделением модулей
- ✗Циклы лечат, импортируя все модули в __init__.py пакета
Разбор темы
- Окружение, импорты и тесты на pytest
Виртуальные окружения и зависимости, как работает импорт и чем опасны циклические импорты, __name__ == "__main__", pytest, фикстуры и mock.patch.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.