Как создать и развернуть вебхук для python-telegram-bot v20
Релиз v20 бота python-telegram-bot внес значительные структурные изменения. Согласно документации, Вся сетевая и вводно-выводная логика теперь работает через функции корутины (такие как async def...). В частности, все методы класса telegram.Bot, которые делают запросы к API бота, теперь являются функциями корутины и требуют...
Выпуск v20 python-telegram-bot внес большие структурные изменения. В соответствии с документацией:
«Вся логика, связанная с сетью и вводом/выводом, теперь работает через функции-корутины (т.е. функции типа
async def ...
). В частности, все методы классаtelegram.Bot
, которые делают запросы к API Bot, теперь являются функциями-корутинами и их нужно ожидать с помощью ключевого словаawait
» — списки изменений в python-telegram-bot v20
Процесс перехода от версии python-telegram-bot 13 до версии 20 оказался более сложным, чем я сначала ожидал. Конвертация синхронных функций def
в async def
и добавление await
к новым корутинам было довольно простым. Но главной сложностью было найти подробную документацию о том, как «создавать и разворачивать webhooks python-telegram-bot v20 в рабочей среде».
В этой статье я объясню почему и как я сменил:
- python-telegram-bot v13 → v20
- Flask → FastAPI
- Gunicorn → Gunicorn + Uvicorn
Почему обновиться с v13 на v20?
v13.x и более ранние версии больше не поддерживаются командой разработчиков python-telegram-bot. Если Telegram API вводит новые функции, они будут доступны только в версии v20 и выше.
Почему использовать вебхук, а не опрос?
Большинство примеров, предоставленных командой разработчиков python-telegram-bot, используют Application.run_polling
. Но вебхуки, как правило, рекомендуются перед опросом для большинства случаев использования ботов Telegram, потому что при опросе вашему боту постоянно приходится делать запросы к серверам Telegram, что может потреблять значительные ресурсы. С другой стороны, вебхуки предлагают расширенный функционал, обновляются быстрее и масштабируются лучше.
Трудности использования Flask с python-telegram-bot v20
Использование WGSI, такого как Flask, с python-telegram-bot v20 неудобно.
Flask, WSGI (Web Server Gateway Interface), синхронный и может обрабатывать только один запрос одновременно. Но вы все равно можете использовать asyncio.run()
для выполнения асинхронных функций в Flask, как в примере создания пользовательского вебхук-бота, предоставленном командой разработчиков python-telegram-bot.
asyncio.run()
запускает цикл событий и выполняет заданную корутину, пока она не завершится. Если перед или после обработки запроса выполняются асинхронные задачи, эти задачи будут выполняться в отдельном цикле событий.
# Код из https://docs.python-telegram-bot.org/en/v20.6/examples.customwebhookbot.htmlwebserver = uvicorn.Server( config=uvicorn.Config( app=WsgiToAsgi(flask_app), port=PORT, use_colors=False, host="127.0.0.1", ))async with application: await application.start() await webserver.serve() # запуск веб-сервера бота await application.stop()
Однако эта реализация немного неудобна, потому что Flask несовместим с асинхронными глобальными объектами.
Примеры в документации не подходят для производственных сред.
Использование asyncio.run()
в качестве точки входа в производстве обычно не рекомендуется. Функция asyncio.run()
предназначена для разработки и тестирования и может не обеспечивать такой же уровень надежности и надежности, как производственные серверы, такие как Gunicorn или UWSGI.
Эти серверы предлагают множество дополнительных функций, таких как журналирование, мониторинг и проверка состояния, которые необходимы для обеспечения стабильности и безопасности производственного приложения.
Если вы хотите развернуть своего бота в продакшн, то гораздо лучше использовать ASGI (Asynchronous Server Gateway Interface) с реализацией веб-сервера ASGI.
Как это сделать – миграция и развёртывание
От Flask (WSGI) к FastAPI (AGSI)
Перенос Flask-приложения на ASGI несложен. Я выбрал FastAPI, потому что здесь я нашел подробный учебник по миграции. Синтаксис обоих фреймворков довольно похож, что означает, что вам не придется вносить слишком много изменений в код.
# От python-telegram-bot v20application = ( Application.builder() .updater(None) .token(<your-bot-token>) # замените <your-bot-token> .read_timeout(7) .get_updates_read_timeout(42) .build())# От FastAPI@asynccontextmanagerasync def lifespan(app: FastAPI): async with application: await application.start() yield await application.stop()
Quart представляет собой вполне приемлемую альтернативу, но не предлагает поддержки для развертывания с использованием Uvicorn, который я адаптировал из скрипта, предоставленного командой python-telegram-bot.
Рабочий пример
Приведенный ниже код показывает минимальный пример использования FastAPI для создания вебхука python-telegram-bot v20. Этот бот будет отвечать “starting…” при получении команды /start
.
# main.pyfrom contextlib import asynccontextmanagerfrom http import HTTPStatusfrom telegram import Updatefrom telegram.ext import Application, CommandHandlerfrom telegram.ext._contexttypes import ContextTypesfrom fastapi import FastAPI, Request, Response# Инициализация python telegram botptb = ( Application.builder() .updater(None) .token(<your-bot-token>) # замените <your-bot-token> .read_timeout(7) .get_updates_read_timeout(42) .build())@asynccontextmanagerasync def lifespan(_: FastAPI): await ptb.bot.setWebhook(<your-webhook-url>) # замените <your-webhook-url> async with ptb: await ptb.start() yield await ptb.stop()# Инициализация FastAPI приложения (аналог Flask)app = FastAPI(lifespan=lifespan)@app.post("/")async def process_update(request: Request): req = await request.json() update = Update.de_json(req, ptb.bot) await ptb.process_update(update) return Response(status_code=HTTPStatus.OK)# Пример обработчикаasync def start(update, _: ContextTypes.DEFAULT_TYPE): """Send a message when the command /start is issued.""" await update.message.reply_text("starting...")ptb.add_handler(CommandHandler("start", start))
Чтобы запустить бота, установите все необходимые зависимости с помощью pip и выполните команду запуска: gunicorn main:app -k uvicorn.workers.UvicornWorker
.
Этот отрывок кода адаптирован из реального Telegram-бота в продакшене. Здесь вы можете посмотреть исходный код @cron_telebot, чтобы увидеть, как он реализован. Не стесняйтесь адаптировать скрипт под свой случай использования.
Заключение
В этой статье мы узнали, как создать и развернуть вебхук python-telegram-bot v20.
Надеюсь, этот учебник вам помог. Если вам понравилась эта статья, пожалуйста, подпишитесь на меня в Medium, чтобы показать свою поддержку.
Спасибо за прочтение!
Leave a Reply