如何在python-telegram-bot的for循环中获取用户下一条消息?
解决Telegram Bot循环中获取用户下一条消息的问题
核心错误分析
- 阻塞异步循环:
time.sleep(10)会直接阻塞bot的异步事件循环,这段时间内bot无法接收或处理任何用户消息,自然拿不到输入的tag。 - 错误的handler注册方式:在循环内动态注册
MessageHandler无效——Telegram Bot的handler是全局注册的,重复添加会引发逻辑冲突,且无法和当前循环的应用上下文绑定。
正确实现方案:对话状态管理
利用Telegram Bot的ConversationHandler和context.user_data跟踪对话状态,分步骤收集每个应用的tag,避免阻塞且逻辑清晰。
步骤1:定义对话状态与处理器
from telegram import Update from telegram.ext import ( ContextTypes, MessageHandler, filters, CallbackQueryHandler, ConversationHandler ) import pandas as pd # 定义对话状态常量 WAITING_FOR_TAG = 1 async def end(update: Update, context: ContextTypes.DEFAULT_TYPE): await update.callback_query.edit_message_reply_markup(reply_markup=None) # 解析回调数据 callback_data = update.callback_query.data.split(',') subsystem = callback_data[0] env = callback_data[1] # 从谷歌表格获取应用列表 gc = GoogleSheetsUpdater().connect() sheet_url = f"https://docs.google.com/spreadsheets/d/{config['DEFAULT']['spreadsheetId']}" sheet = gc.open_by_url(sheet_url) ws = sheet.get_worksheet(0) df = pd.DataFrame(ws.get_all_records()) apps_list = df['app'][df['subsystem'] == subsystem].tolist() # 初始化对话状态,保存到用户数据中 context.user_data.update({ 'apps_list': apps_list, 'current_index': 0, 'subsystem': subsystem }) # 发送第一个tag请求 first_app = apps_list[0] await update.callback_query.edit_message_text( text=f"Please, send me a tag for {first_app} in {subsystem}:" ) # 进入等待用户输入的状态 return WAITING_FOR_TAG async def tag_handler(update: Update, context: ContextTypes.DEFAULT_TYPE): tag = update.message.text user_data = context.user_data # 获取当前处理的应用信息 current_idx = user_data['current_index'] current_app = user_data['apps_list'][current_idx] subsystem = user_data['subsystem'] # 这里添加tag的处理逻辑(比如写入表格) print(f"Tag received for {current_app}: {tag}") # 处理下一个应用 current_idx += 1 if current_idx < len(user_data['apps_list']): next_app = user_data['apps_list'][current_idx] await update.message.reply_text( text=f"Please, send me a tag for {next_app} in {subsystem}:" ) user_data['current_index'] = current_idx return WAITING_FOR_TAG else: # 所有应用处理完成 await update.message.reply_text("All tags have been collected successfully!") user_data.clear() return ConversationHandler.END
步骤2:注册对话处理器
在bot初始化时,注册ConversationHandler管理整个对话流程:
# 替换成你的callback触发模式(比如匹配以'end'开头的回调数据) conv_handler = ConversationHandler( entry_points=[CallbackQueryHandler(end, pattern=r'^end.*$')], states={ WAITING_FOR_TAG: [MessageHandler(filters.TEXT & ~filters.COMMAND, tag_handler)] }, fallbacks=[] # 可添加/取消等命令的处理器,用于中断对话 ) # 添加到应用中 application.add_handler(conv_handler)
方案优势
- 非阻塞:完全基于异步逻辑,bot在等待用户输入时仍能处理其他请求。
- 状态隔离:每个用户的对话状态保存在
user_data中,不会和其他用户的流程冲突。 - 逻辑清晰:通过
ConversationHandler明确划分对话阶段,避免循环内的混乱逻辑。
内容的提问来源于stack exchange,提问作者Bergan Jar
相关产品推荐
相关产品推荐

