如何在Python Telegram机器人中实现循环暂停等待用户输入后继续
Python Telegram 机器人暂停循环等待用户确认的实现方案
Telegram 机器人为事件驱动架构,无法直接在同步遍历循环里阻塞等待用户输入,核心实现思路是将匹配好的职位列表、当前遍历索引存入用户会话状态,每次用户确认后再取下一个职位推送,拆分原有同步循环为多次事件响应。
完整实现代码(基于 python-telegram-bot v20+ 异步版本)
from telegram import InlineKeyboardMarkup, InlineKeyboardButton from telegram.ext import CallbackQueryHandler, ConversationHandler, CommandHandler # 定义等待用户确认的状态码 WAITING_FOR_CONFIRM = 1 # 职位搜索触发入口,可绑定到用户指令比如/search_jobs async def start_job_search(update, context): # 替换为你自己的用户信息、全量职位列表获取逻辑 user = context.user_data.get("user_info") jobs = get_all_jobs() # 预过滤所有符合条件的职位,避免后续重复遍历 matched_jobs = [] for job in jobs: if int(job[6]) <= int(user.dpr): if str(user.sex) == 'זכר': if int(user.profil) >= int(job[7]) and int(user.profil) <= int(job[8]): matched_jobs.append(job) else: if int(user.profil) >= int(job[9]) and int(user.profil) <= int(job[10]): matched_jobs.append(job) if not matched_jobs: await update.message.reply_text("未找到符合条件的职位") return ConversationHandler.END # 存储匹配结果和当前遍历索引到用户会话 context.user_data["matched_jobs"] = matched_jobs context.user_data["current_job_idx"] = 0 # 推送第一个符合条件的职位 await send_current_job(update, context) return WAITING_FOR_CONFIRM # 统一推送当前索引对应的职位 async def send_current_job(update, context): matched_jobs = context.user_data["matched_jobs"] current_idx = context.user_data["current_job_idx"] job = matched_jobs[current_idx] # 生成职位跳转按钮+继续/停止确认按钮 reply_markup = InlineKeyboardMarkup([ [InlineKeyboardButton(text='לאתר מתגייסים', url=job[3])], [ InlineKeyboardButton(text="继续查看下一个", callback_data="continue_job"), InlineKeyboardButton(text="停止推送", callback_data="stop_job") ] ]) msg_content = f"<b>{job[1]}</b>\n{job[2]}" if update.callback_query: await update.callback_query.answer() await update.callback_query.message.reply_text(msg_content, reply_markup=reply_markup, parse_mode="HTML") else: await update.message.reply_text(msg_content, reply_markup=reply_markup, parse_mode="HTML") # 处理用户的确认回调 async def handle_confirm(update, context): query = update.callback_query action = query.data if action == "stop_job": await query.answer("已停止职位推送") await query.message.reply_text("你可以随时重新发起职位搜索") # 清空临时会话状态 context.user_data.pop("matched_jobs", None) context.user_data.pop("current_job_idx", None) return ConversationHandler.END if action == "continue_job": current_idx = context.user_data["current_job_idx"] + 1 total_count = len(context.user_data["matched_jobs"]) if current_idx >= total_count: await query.answer("所有符合条件的职位已推送完毕") await query.message.reply_text("没有更多符合条件的职位了") context.user_data.pop("matched_jobs", None) context.user_data.pop("current_job_idx", None) return ConversationHandler.END # 更新索引推送下一个职位 context.user_data["current_job_idx"] = current_idx await send_current_job(update, context) return WAITING_FOR_CONFIRM # 将会话处理器注册到你的bot实例 job_conv_handler = ConversationHandler( entry_points=[CommandHandler("search_jobs", start_job_search)], states={ WAITING_FOR_CONFIRM: [CallbackQueryHandler(handle_confirm, pattern="^(continue_job|stop_job)$")] }, fallbacks=[] ) application.add_handler(job_conv_handler)
如果你使用的是 v13 及更早的同步版本 python-telegram-bot,只需移除所有 async/await 关键字,将异步方法调用改为普通同步调用即可,逻辑完全一致。
注意事项
- 不要使用
input()或time.sleep()之类的同步阻塞方法等待用户输入,会导致整个机器人进程卡顿无响应 - 预过滤全量匹配职位可以避免每次用户点击后重复遍历全量职位列表,降低性能损耗
- 职位推送完毕或用户主动停止后,记得清空用户会话里的临时状态,避免占用内存和后续逻辑冲突
内容的提问来源于stack exchange,提问作者Floyd1337
相关产品推荐
相关产品推荐

