Принцип регистрации хендлеров

Принцип регистрации хендлеров

Latand

Сейчас мы кратко рассмотрим как работает принцип регистрации хендлеров и доставки апдейтов до наших функций-обработчиков.

Содержание статьи

├── Порядок регистрации хендлеров
├── Доставка апдейта до нужного хендлера
├── Движение объекта Dispatcher по модулям


Порядок регистрации хендлеров

Предположим у нас есть такой хендлер:

Что же тут делает декоратор message_handler?

Открываем источник и видим такое:

Декоратор вызывает функцию register_message_handler и передает в нее все условия (фильтры), что мы указали и callback (функцию, в которой мы хотим обрабатывать наше сообщение).

А что же происходит в функции register_message_handler?

Тут регистрируются наши условия (фильтры) и выполняется метод register у объекта message_handlers. То есть, если мы возьмем вместо декоратора просто функцию dp.register_message_handler - будет тот же результат, что и декоратором.

Давайте разберемся, что же это за функция register?

Есть некий класс Handler, у которого есть атрибут-список хендлеров, называется он self.handlers

И выполняя функцию register, мы добавляем наш HandlerObj, в котором будет нужная нам функция с нужными фильтрами, в список хендлеров этого типа (например message или callback_query).


Доставка апдейта до нужного хендлера

Если посмотреть в объект Dispatcher, то увидим следующее:

У диспатчера есть набор атрибутов-хендлеров. Это и message_handlers, и edited_message_handlers и channel_post_handlers и другие. Это те самые объекты типа Handler, у которого есть список self.handlers, в который мы добавляем наши обработчики.

Теперь, когда нам понятно как регистрируются наши хендлеры, давайте глянем, что происходит, когда приходит апдейт.

У Dispatcher есть метод process_update, который проверяет тип апдейта, и выполняет функцию notify у нужного типа хендлеров.

Заходим в метод notify и видим:

  1. Если на типа хендлеров установлен ключ миддлваря, то тригеррится функция pre_process_ у необходимого типа апдейтов. Подробнее про миддлвари тут.
  2. Происходит итерация по ЗАРЕГИСТРИРОВАННЫМ хендлерам этого типа (например message). Тот самый список, в который делали append в объекте Handler.
  3. Идет проверка на фильтры в каждом хендлере. Если все условия не выполняются - поднимается ошибка FilterNotPassed, и в этой строке она обрабатывается и происходит переход к следующему хендлеру.
  4. Теперь, когда ошибка не случилась- фильтры подошли, триггерится уже миддлварь ключа process_
  5. После чего выполняется та функция, которую мы зарегистрировали с нужными параметрами (переданными, как самим аиограмом, так и через миддлвари).


Движение объекта Dispatcher по модулям

Теперь, собственно, как я регистрирую хендлеры в проекте, где много разных модулей.

  1. В одном модуле (loader.py) инициализируются важные для работы переменные - bot, dispatcher. Их я импортирую в модулях хендлеров и с помощью декоратора добавляю в dp.message_handlers (например) мои функции.
  2. Каждый раз когда я делаю импорт dp из модуля хендлеров - Python понимает, что я использую тот же самый объект dp из файла loader.py и просто пишет на него же новые хендлеры из других модулей моего проекта.
  3. После чего, готовый объект диспатчера, со всеми навешенными на него хендлерами, передается в модуль app.py, где и происходит запуск бота .

Графическую схему работы можно посмотреть в посте тут.

Report Page