You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python的pyTeleBot实现for循环等待内联键盘点击暂停

解决pyTeleBot投票机器人等待用户回调再继续的问题

你的核心问题是同步循环无法等待用户的内联键盘回调——原来的代码用for循环直接遍历所有包,加上time.sleep只是阻塞机器人线程,根本没法真正等待用户交互。pyTeleBot的回调是异步触发的,必须通过状态管理来关联用户的操作和投票流程。

下面是具体的实现方案:

1. 核心思路

  • 用一个全局字典记录每个用户的当前投票进度(比如处理到第几个包)
  • 把投票流程拆成「初始化投票」和「处理下一个包」两个部分
  • 用户点击内联按钮后,在回调函数中更新状态并触发下一个包的处理

2. 修改后的完整代码

第一步:定义用户状态存储

import os
import telebot
from telebot import types

bot = telebot.TeleBot("你的Bot Token")

# 存储用户的投票状态:键为用户ID,值为当前处理的包索引(从0开始)
user_vote_state = {}

# 假设你的db_add_vote函数已经实现
def db_add_vote(user_id, pack_num, image_num):
    # 这里写你的投票记录逻辑
    pass

第二步:初始化投票流程

def start_vote(message):
    user_id = message.from_user.id
    # 获取所有投票包,建议排序保证顺序稳定
    entries = sorted(os.listdir('entries/'))
    
    if not entries:
        bot.reply_to(message, "暂无可用的投票包")
        return
    
    # 初始化用户状态,从第0个包开始处理
    user_vote_state[user_id] = 0
    # 触发第一个包的展示
    process_next_pack(user_id, entries)

第三步:封装包处理逻辑

def process_next_pack(user_id, entries):
    current_idx = user_vote_state[user_id]
    
    # 检查是否所有包都处理完毕
    if current_idx >= len(entries):
        bot.send_message(user_id, "所有投票包已处理完成!")
        del user_vote_state[user_id]  # 清除用户状态,释放内存
        return
    
    entry = entries[current_idx]
    entry_num = current_idx + 1  # 包编号从1开始展示给用户
    bot.send_message(user_id, f"Pack {entry_num}")
    
    # 获取当前包下的所有图片,同样建议排序
    images = sorted(os.listdir(f'entries/{entry}/'))
    keyboard_buttons = []
    
    for image in images:
        image_num = images.index(image) + 1
        # 用with语句打开图片,避免文件句柄泄漏
        with open(f'entries/{entry}/{image}', 'rb') as photo_file:
            bot.send_photo(
                user_id,
                photo_file,
                caption=str(image_num),
                parse_mode="HTML"
            )
        # 回调数据加入当前包索引,方便后续更新状态
        button = types.InlineKeyboardButton(
            str(image_num),
            callback_data=f'{entry_num}_{image_num}_{current_idx}'
        )
        keyboard_buttons.append(button)
    
    # 构建内联键盘
    voting_markup = types.InlineKeyboardMarkup()
    for btn in keyboard_buttons:
        voting_markup.add(btn)
    
    bot.send_message(user_id, 'Choose an image:', reply_markup=voting_markup)

第四步:修改回调函数,触发下一轮投票

def callback_inline(call):
    user_id = call.from_user.id
    # 拆分回调数据:包编号、图片编号、当前包索引
    data_parts = call.data.split('_')
    pack_num = data_parts[0]
    image_num = data_parts[1]
    current_idx = int(data_parts[2])
    
    # 记录用户投票
    db_add_vote(user_id, pack_num, image_num)
    
    # 更新消息反馈用户
    bot.edit_message_text(
        chat_id=call.message.chat.id,
        message_id=call.message.message_id,
        text=f"You've chosen image num {image_num}",
        reply_markup=None
    )
    
    # 更新用户状态,处理下一个包
    if user_id in user_vote_state:
        user_vote_state[user_id] = current_idx + 1
        entries = sorted(os.listdir('entries/'))
        process_next_pack(user_id, entries)

# 注册处理器
bot.register_message_handler(start_vote, commands=['start_vote'])
bot.register_callback_query_handler(callback_inline, func=lambda call: True)

bot.polling()

3. 关键说明

  • 状态隔离:user_vote_state字典保证每个用户的投票进度独立,不会互相干扰
  • 回调数据扩展:在回调数据中加入当前包的索引,确保能准确找到用户的进度位置
  • 资源清理:所有包处理完后删除用户状态,避免内存冗余
  • 顺序稳定:用sorted()处理目录列表,避免每次运行时包或图片的顺序随机变化

内容的提问来源于stack exchange,提问作者jenny Thif

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 16:01:10