同一代码运行FastAPI与Telegram Bot报错,求解决方法
问题:FastAPI集成Telegram Bot线程运行报错
我用FastAPI开发了一个处理Webhook的Python应用,尝试集成Telegram Bot,但使用threading启动Telegram服务时无法正常工作,出现以下错误:
Uvicorn running on http://0.0.0.0:8383 (Press CTRL+C to quit) Bot is running... Exception in thread Thread-2 (run_telegram_bot): Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 1016, in _bootstrap_inner self.run() File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py", line 953, in run self._target(*self._args, **self._kwargs) File "/Users/yosef/uni/Uni chat store/index.py", line 23, in run_telegram_bot TelegramNotification().lunch_bot() File "/Users/yosef/uni/Uni chat store/utils/telegram/send_notifictions.py", line 51, in lunch_bot application.run_polling(1.0) File "/Users/yosef/.local/share/virtualenvs/Uni_chat_store-eDiP6l1M/lib/python3.10/site-packages/telegram/ext/_application.py", line 836, in run_polling return self.__run( File "/Users/yosef/.local/share/virtualenvs/Uni_chat_store-eDiP6l1M/lib/python3.10/site-packages/telegram/ext/_application.py", line 1007, in __run loop = asyncio.get_event_loop() File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/asyncio/events.py", line 656, in get_event_loop raise RuntimeError('There is no current event loop in thread %r.' RuntimeError: There is no current event loop in thread 'Thread-2 (run_telegram_bot)'. /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/threading.py:1018: RuntimeWarning: coroutine 'Updater.start_polling' was never awaited self._invoke_excepthook(self) RuntimeWarning: Enable tracemalloc to get the object allocation traceback
相关代码
TelegramNotification类的启动函数
def lunch_bot(self): application = Application.builder().token(self.BOT_TOKEN).build() print('Bot is running...') # Commands application.add_handler(CommandHandler('start', self.start)) # Run bot application.run_polling(1.0)
index.py文件内容
from fastapi import FastAPI from routers import whatsapp_webhook, payment_method_form from fastapi.middleware.cors import CORSMiddleware import uvicorn from utils.telegram.send_notifictions import TelegramNotification import threading app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["*"], # Allows all origins allow_credentials=True, allow_methods=["*"], # Allows all methods allow_headers=["*"], # Allows all headers ) app.include_router(whatsapp_webhook.router) app.include_router(payment_method_form.router) def run_telegram_bot(): TelegramNotification().lunch_bot() # run the whatsapp webhook def run_whatsapp_webhook(): uvicorn.run("index:app", host="0.0.0.0", port=8383) if __name__ == '__main__': threading.Thread(target=run_whatsapp_webhook).start() threading.Thread(target=run_telegram_bot).start()
解决方案
报错原因是子线程默认没有创建asyncio事件循环,而python-telegram-bot v20+版本的run_polling依赖异步事件循环。只需修改run_telegram_bot函数,在子线程中手动创建并设置事件循环即可:
def run_telegram_bot(): import asyncio # 为子线程创建并设置asyncio事件循环 loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) TelegramNotification().lunch_bot()
如果希望更贴合异步编程规范,也可以把lunch_bot改为异步函数,再通过事件循环运行:
修改TelegramNotification类的lunch_bot方法
async def lunch_bot(self): application = Application.builder().token(self.BOT_TOKEN).build() print('Bot is running...') # Commands application.add_handler(CommandHandler('start', self.start)) # Run bot await application.run_polling(1.0)
修改run_telegram_bot函数
def run_telegram_bot(): import asyncio loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(TelegramNotification().lunch_bot())
这样修改后,Telegram Bot就能在子线程中正常运行,同时不影响FastAPI的Webhook服务。
内容的提问来源于stack exchange,提问作者Yosef Schwartz
相关产品推荐
相关产品推荐

