Обработка ошибок¶
В процессе работы бота могут возникать исключения (ошибки в коде, недоступность внешних сервисов, ошибки валидации). maxo предоставляет встроенный механизм для их перехвата и обработки, чтобы ваш бот не падал при возникновении проблем.
Как это работает¶
Dispatcher автоматически регистрирует глобальную мидлварь ErrorMiddleware. Она оборачивает процесс обработки каждого события в блок try...except.
Если в любом из хендлеров или мидлварей возникает необработанное исключение (наследуемое от Exception), оно перехватывается, и создается новое событие типа ErrorEvent.
Это событие затем отправляется в диспетчер, где вы можете поймать его с помощью специальных обработчиков ошибок.
Регистрация обработчика¶
Для перехвата ошибок используется декоратор @router.error() (или @dispatcher.error()).
from maxo.routing.updates import ErrorEvent
@router.error()
async def global_error_handler(event: ErrorEvent):
# Логируем ошибку
print(f"Произошла ошибка: {event.exception}")
# Можно попробовать ответить пользователю, если контекст позволяет
# (но учтите, что update внутри event может быть любым)
Фильтрация ошибок¶
Вы можете фильтровать ошибки по их типу или сообщению, чтобы обрабатывать разные ситуации по-разному.
ExceptionTypeFilter¶
Фильтрует ошибки по классу исключения.
from maxo.routing.filters import ExceptionTypeFilter
from maxo.routing.updates import ErrorEvent
from maxo.types import UpdateContext
# Перехват ошибок конкретного типа
@router.error(ExceptionTypeFilter(ValueError))
async def value_error_handler(
event: ErrorEvent,
update_context: UpdateContext,
):
await event.bot.send_message(
chat_id=update_context.chat_id,
text="Вы ввели некорректные данные!",
)
ExceptionMessageFilter¶
Фильтрует ошибки по тексту сообщения (поддерживает регулярные выражения).
from maxo.routing.filters import ExceptionMessageFilter
from maxo.routing.updates import ErrorEvent
@router.error(ExceptionMessageFilter(r"Access denied"))
async def access_denied_handler(event: ErrorEvent):
...
Аргументы обработчика¶
В обработчик ошибки передаются следующие аргументы:
event: объект
ErrorEvent. Содержит: -event.exception- само исключение. -event.update- исходное событие (Update), при обработке которого возникла ошибка.ctx: контекст выполнения.
Либо «заинлайненные» ключи ctx
Пример¶
import logging
from maxo.routing.ctx import Ctx
from maxo.routing.filters import ExceptionTypeFilter
from maxo.routing.updates import ErrorEvent, MessageCreated
from maxo.types import UpdateContext
class MyCustomError(Exception):
pass
@router.message_created()
async def my_handler(update: MessageCreated, ctx: Ctx):
if update.message.body.text == "boom":
raise MyCustomError("Ба-бах!")
@router.error(ExceptionTypeFilter(MyCustomError))
async def error_handler(event: ErrorEvent, update_context: UpdateContext):
# Пытаемся отправить сообщение в тот же чат, где произошла ошибка
try:
await event.bot.send_message(
chat_id=update_context.chat_id,
text=f"Ой, что-то сломалось: {event.exception}",
)
except Exception:
# Если не удалось отправить сообщение об ошибке, просто логируем
logging.exception("Не удалось отправить уведомление об ошибке")