Telegram机器人首次运行正常,后续请求无法重新查询数据库及进入fetchall循环的技术问询
问题分析与修复方案
我帮你捋清楚问题出在哪,以及怎么解决:
核心问题根源
你遇到的问题本质是全局游标只在程序启动时执行了一次数据库查询,第一次请求就把结果集耗尽了:
- 程序刚启动时,你执行了
cur.execute("SELECT idTelegram, Troncal FROM troncales"),这个查询的结果存在游标cur里。 - 第一次处理请求时,
cur.fetchall()把结果集里的所有数据都取出来了,游标直接跑到了结果集的末尾。 - 后续再调用
cur.fetchall(),游标已经没有数据可以返回了,自然进不了循环。 - 你写的
cur.reset()完全没起到作用——它被放在所有break语句的后面,只要循环里触发了任何一个break,这个重置代码根本不会执行,游标就一直停在结果集末尾。
修复方案(推荐第一种)
方案1:每次请求重新查询数据库(最稳妥)
把数据库查询的逻辑移到messageHandler函数里,每次收到用户请求时,重新从数据库拉取最新数据,这样就不会依赖全局游标的状态了:
# 全局只保留数据库连接(如果机器人长期运行,后续可以考虑用连接池) miConexion = mysql.connector.connect( host='localhost', user= 'root', passwd='', db='validacion' ) ConsultarSaldoSw2 = "Consultar Saldo SW2" def startCommand(update: Update, context: CallbackContext): buttons = [[KeyboardButton(ConsultarSaldoSw2)]] context.bot.send_message(chat_id=update.effective_chat.id, text="Bienvenido", reply_markup=ReplyKeyboardMarkup(buttons)) def messageHandler(update: Update, context: CallbackContext): bot = context.bot updateMsg = getattr(update, 'message', None) messageId = updateMsg.message_id chatId = update.message.chat_id userName = update.effective_user['username'] text = update.message.text if ConsultarSaldoSw2 in update.message.text: context.bot.send_message(chat_id=update.effective_chat.id, text="Ingresa tu Nombre de Troncal") return # 每次请求都重新创建游标并执行查询 cur = miConexion.cursor(buffered=True) try: cur.execute("SELECT idTelegram, Troncal FROM troncales") # 现在每次都能拿到最新的数据库数据 for idTelegram, Troncal in cur.fetchall() : print("prueba") if userName in idTelegram: if text in Troncal: print(f"Troncal Correcta {text}") Saldo = client.getAccountInfo({'username': text}) SaldoESP1 = f"{Saldo['balance']}" TroncalCompleta = f"{Saldo['authname']}" Moneda = f"{Saldo['base_currency']}" print(Saldo) integer = float(SaldoESP1) # 正负情况的转换逻辑是一样的,不用分开写 Convertir = str(integer * -1) context.bot.send_message( chat_id=update.effective_chat.id, text=f"{TroncalCompleta} es {Convertir} {Moneda}" ) break else: print(f"Troncal Incorrecto {text}") context.bot.send_message(chat_id=update.effective_chat.id, text="No estas permitido para ver esto") break else: print(f"Usuario Incorrecto {userName}") context.bot.send_message(chat_id=update.effective_chat.id, text="Usuario Incorrecto Validalo con soporte") break finally: # 用完游标及时关闭,避免资源浪费 cur.close() # Telegram机器人初始化代码不变 updater = Updater(token="") dispatcher = updater.dispatcher dispatcher.add_handler(CommandHandler("start", startCommand)) dispatcher.add_handler(MessageHandler(Filters.text, messageHandler)) updater.start_polling()
方案2:复用全局游标,但每次请求重新执行查询
如果你想保留全局游标,那每次处理请求前必须重新执行execute,刷新结果集:
# 全局定义连接和游标 miConexion = mysql.connector.connect( host='localhost', user= 'root', passwd='', db='validacion' ) cur = miConexion.cursor(buffered=True) ConsultarSaldoSw2 = "Consultar Saldo SW2" def startCommand(update: Update, context: CallbackContext): buttons = [[KeyboardButton(ConsultarSaldoSw2)]] context.bot.send_message(chat_id=update.effective_chat.id, text="Bienvenido", reply_markup=ReplyKeyboardMarkup(buttons)) def messageHandler(update: Update, context: CallbackContext): bot = context.bot updateMsg = getattr(update, 'message', None) messageId = updateMsg.message_id chatId = update.message.chat_id userName = update.effective_user['username'] text = update.message.text if ConsultarSaldoSw2 in update.message.text: context.bot.send_message(chat_id=update.effective_chat.id, text="Ingresa tu Nombre de Troncal") return # 每次请求前重新执行查询,重置结果集 cur.execute("SELECT idTelegram, Troncal FROM troncales") for idTelegram, Troncal in cur.fetchall() : print("prueba") if userName in idTelegram: if text in Troncal: print(f"Troncal Correcta {text}") Saldo = client.getAccountInfo({'username': text}) SaldoESP1 = f"{Saldo['balance']}" TroncalCompleta = f"{Saldo['authname']}" Moneda = f"{Saldo['base_currency']}" print(Saldo) integer = float(SaldoESP1) Convertir = str(integer * -1) context.bot.send_message( chat_id=update.effective_chat.id, text=f"{TroncalCompleta} es {Convertir} {Moneda}" ) break else: print(f"Troncal Incorrecto {text}") context.bot.send_message(chat_id=update.effective_chat.id, text="No estas permitido para ver esto") break else: print(f"Usuario Incorrecto {userName}") context.bot.send_message(chat_id=update.effective_chat.id, text="Usuario Incorrecto Validalo con soporte") break # Telegram初始化代码不变 updater = Updater(token="") dispatcher = updater.dispatcher dispatcher.add_handler(CommandHandler("start", startCommand)) dispatcher.add_handler(MessageHandler(Filters.text, messageHandler)) updater.start_polling()
额外优化小建议
- 连接稳定性:长期运行的机器人可能会遇到数据库连接断开的问题,建议后续添加连接状态检查,或者使用
mysql-connector-python的连接池功能。 - 代码精简:你之前对正负数值的转换逻辑完全一样,我已经帮你合并了,减少冗余。
- 错误处理:可以给数据库操作加上
try-except捕获异常,避免数据库出错导致机器人直接崩溃。
内容的提问来源于stack exchange,提问作者Benito Barrios Ruiz
相关产品推荐
相关产品推荐

