使用python-telegram-bot与asyncio遇Event Loop Already Running错误求助
解决python-telegram-bot异步运行时的事件循环错误
错误原因
你遇到的RuntimeError: This event loop is already running和Cannot close a running event loop,核心问题是重复调用了事件循环相关的阻塞逻辑:
application.run_polling()本身是阻塞式异步函数,内部已包含维持Bot运行、等待停止信号的逻辑- 额外添加的
await application.idle()会再次尝试占用事件循环,导致冲突
修复方案
方案1:仅使用run_polling()(推荐)
删除多余的await application.idle(),直接用run_polling()维持Bot运行:
import asyncio from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, filters from imdb import IMDb # 确保处理器为异步函数 async def init(update, context): await update.message.reply_text("欢迎使用电影推荐Bot!请输入你喜欢的电影类型") async def genres_selected(update, context): # IMDbPY是同步库,用asyncio.to_thread避免阻塞事件循环 ia = IMDb() movies = await asyncio.to_thread(ia.search_movie, update.message.text) if movies: await update.message.reply_text(f"为你推荐:{movies[0]['title']} ({movies[0].get('year', '')})") else: await update.message.reply_text("未找到相关电影") async def main(): application = ApplicationBuilder().token("YOUR_BOT_TOKEN").build() # 添加处理器 application.add_handler(CommandHandler("start", init)) application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, genres_selected)) # run_polling会一直运行直到收到停止信号(比如Ctrl+C) await application.run_polling() if __name__ == '__main__': asyncio.run(main())
方案2:使用start_polling() + idle()
若需要更灵活控制Bot启动/停止流程,可启动轮询任务后用idle()等待停止:
import asyncio from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, filters from imdb import IMDb async def init(update, context): await update.message.reply_text("欢迎使用电影推荐Bot!请输入你喜欢的电影类型") async def genres_selected(update, context): ia = IMDb() movies = await asyncio.to_thread(ia.search_movie, update.message.text) if movies: await update.message.reply_text(f"为你推荐:{movies[0]['title']} ({movies[0].get('year', '')})") else: await update.message.reply_text("未找到相关电影") async def main(): application = ApplicationBuilder().token("YOUR_BOT_TOKEN").build() application.add_handler(CommandHandler("start", init)) application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, genres_selected)) # 启动轮询任务(非阻塞) await application.start_polling() # 等待Bot停止信号 await application.idle() if __name__ == '__main__': asyncio.run(main())
额外注意事项
- IMDbPY是同步库,直接在异步处理器中调用会阻塞事件循环,必须用
asyncio.to_thread()将同步调用放到线程池执行。 - 所有处理器函数必须定义为
async def,否则会与异步Application框架冲突。
内容的提问来源于stack exchange,提问作者Saud Binnouh
相关产品推荐
相关产品推荐

