如何终止Telegram机器人application.run_polling()循环并恢复代码执行?
解决Telegram机器人
run_polling()无法终止、后续代码无法执行的问题 核心问题
application.run_polling()是阻塞式方法,调用后会直接占据主线程,导致bot_start()之后的代码完全没机会执行。同时你的stop命令终止逻辑存在错误,没法正确停止机器人。
解决方案
1. 改用非阻塞/可控的启动方式
别直接依赖run_polling()的阻塞运行,要么用application.start() + application.idle()的组合,要么用异步事件循环管理,既能灵活控制机器人启停,又不会阻塞后续代码。
2. 修正stop命令的终止逻辑
Updater.shutdown(application.bot)是错误用法,Updater的shutdown()不需要传参数,正确终止流程是:发送终止提示 → 停止polling → 关闭应用资源 → 退出事件循环。
修正后的完整代码
import asyncio import logging from telegram import Update from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes def bot_start(): application = ApplicationBuilder().token("api_key").build() async def stop(update: Update, context: ContextTypes.DEFAULT_TYPE): await context.bot.send_message(chat_id=update.message.chat_id, text='Terminating Bot...') # 停止polling任务 await application.stop() # 关闭应用所有资源 await application.shutdown() # 退出事件循环,让idle状态结束 loop = asyncio.get_event_loop() loop.stop() async def error(update: Update, context: ContextTypes.DEFAULT_TYPE): err = f"Update: {update}\nError: {context.error}" logging.error(err, exc_info=context.error) # 注意user_id需提前定义或从update中获取 await context.bot.send_message(chat_id=user_id, text=err) application.add_handler(CommandHandler('stop', stop)) application.add_error_handler(error) # 启动polling,允许指定更新类型并丢弃待处理更新 application.run_polling(drop_pending_updates=True, allowed_updates=Update.ALL_TYPES) # 用守护线程启动机器人,避免阻塞主线程 import threading threading.Thread(target=bot_start, daemon=True).start() # 后续代码现在可以正常执行 print("机器人已启动,后续代码开始运行...")
另一种启动方式(基于异步任务)
如果习惯用纯异步逻辑,也可以这样写:
import asyncio import logging from telegram import Update from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes async def run_bot(): application = ApplicationBuilder().token("api_key").build() async def stop(update: Update, context: ContextTypes.DEFAULT_TYPE): await context.bot.send_message(chat_id=update.message.chat_id, text='Terminating Bot...') await application.stop() await application.shutdown() application.add_handler(CommandHandler('stop', stop)) await application.start() await application.idle() # 启动机器人异步任务 asyncio.create_task(run_bot()) # 后续代码不受阻塞 print("机器人启动中,后续代码正常执行...") # 保持主线程运行 asyncio.get_event_loop().run_forever()
内容的提问来源于stack exchange,提问作者Dr. Dark Flames
相关产品推荐
相关产品推荐

