Как работает hot reload¶
В разработке Raito перезагружает файл хендлера в момент сохранения, без перезапуска бота. Эта страница объясняет механику, чтобы вы знали, что он может, а что нет.
Три действующих лица¶
RouterParserИмпортирует один файл как изолированный модуль. Строит spec из пути к файлу, даёт модулю уникальное синтетическое имя, регистрирует его в
sys.modulesдо выполнения (чтобы разрешились dataclass’ы и относительная механика), выполняет модуль и возвращает найденный роутер.RouterLoaderВладеет жизненным циклом одного файла:
loadвключает роутер в диспетчер;unloadубирает его и сбрасывает распарсенный роутер;reloadвыполняетunload, затемload.
Важно, что
unloadзапоминает индекс роутера среди суб-роутеров диспетчера, аloadего восстанавливает, поэтому перезагрузка оставляет роутер на прежнем месте, сохраняя порядок разбора хендлеров.RouterManagerСканирует папку, создаёт по загрузчику на файл и держит наблюдатель.
Цикл перезагрузки¶
Когда файл меняется, менеджер находит его загрузчик и вызывает reload:
unload: роутер убирается из диспетчера, а его распарсенный объект сбрасывается (вNone).load: обращение к роутеру загрузчика заново импортирует файл, поэтому новый код парсится с нуля, а затем роутер регистрируется на сохранённом индексе.
Свежесть берётся из повторного импорта модуля, а не из правки объектов на месте. Именно это делает перезагрузку надёжной: вы всегда получаете ровно тот код, что на диске.
Что перезагружается чисто, а что нет¶
Тела хендлеров перезагружаются прозрачно. Менять то, что делает хендлер, безопасно даже для пользователя посреди сцены, потому что aiogram опознаёт FSM-шаг по строковому имени, а не по объекту Python.
Новые файлы подхватываются: событие
addedсоздаёт загрузчик и грузит роутер.Удалённые файлы выгружают свой роутер.
Побочные эффекты на уровне модуля выполняются заново при каждой перезагрузке, потому что модуль исполняется повторно. Держите работу на этапе импорта в файлах хендлеров минимальной: дорогое состояние стройте в lifespan, а не на верхнем уровне модуля.
Общие модули (хелпер, импортируемый несколькими роутерами) сами по себе не вызывают перезагрузку импортирующих их роутеров; перезагружается только изменённый файл роутера.
Почему только в разработке¶
Наблюдатель (watchfiles.awatch) работает только при production=False. В продакшене нужен фиксированный, проверенный набор роутеров и никаких накладных расходов на слежение за файлами, поэтому setup просто грузит всё один раз и наблюдатель не запускает.
Приоритет и порядок¶
На старте роутеры грузятся сначала с наибольшим приоритетом, что фиксирует их порядок в диспетчере. Перезагрузка возвращает роутер на прежний индекс, поэтому порядок стабилен между правками. Совсем новый файл, добавленный на лету, дописывается в конец, а не вставляется по приоритету, поэтому если строгий порядок важен, перезапустите бота.