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

Telegram机器人部分Inline按钮点击崩溃问题求助

问题描述

我用Python的telebot库开发了一个Telegram货币兑换机器人,在summ函数里创建了7个Inline按钮:

  • btn1(USD/RUB)和btn3(EUR/RUB)点击后机器人直接崩溃
  • 其余按钮可正常运行
  • btn7(OTHER)暂未配置回调逻辑

尝试单独写脚本处理这两个按钮但没解决问题,用VSCode开发无法定位错误,完整代码如下:

import telebot
from currency_converter import CurrencyConverter
from telebot import types


bot = telebot.TeleBot('6427511998:AAGO3q9JS06PLkxQblJFVQ-RNJwEpNBYZ_M')
curency = CurrencyConverter()
amount = 0
buttons = ''

@bot.message_handler(commands=['start'])
def start(message):
    global buttons
    buttons = types.ReplyKeyboardMarkup()
    btn1 = types.KeyboardButton('100')
    btn2 = types.KeyboardButton('200')
    btn3 = types.KeyboardButton('500')
    buttons.row(btn1, btn2, btn3)
    btn4 = types.KeyboardButton('1000')
    btn5 = types.KeyboardButton('2000')
    btn6 = types.KeyboardButton('5000')
    buttons.row(btn4, btn5, btn6)
    bot.send_message(message.chat.id, 'Здарова, напиши сумму', reply_markup=buttons)
    bot.register_next_step_handler(message, summ)
    
def summ(message):
    global amount
    global buttons
    try:
        amount = int(message.text.strip())
    except ValueError:
        bot.send_message(message.chat.id, 'Ошибка. Введите сумму(числовой формат)', reply_markup=buttons)
        bot.register_next_step_handler(message, summ)
        return
    
    if amount > 0:
        buttons2 = types.InlineKeyboardMarkup(row_width=3)
        btn1 = types.InlineKeyboardButton('USD/RUB', callback_data='USD/RUB')
        btn2 = types.InlineKeyboardButton('USD/EUR', callback_data='USD/EUR')
        btn3 = types.InlineKeyboardButton('EUR/RUB', callback_data='EUR/RUB')
        btn4 = types.InlineKeyboardButton('RUB/USD', callback_data='RUB/USD')
        btn5 = types.InlineKeyboardButton('EUR/USD', callback_data='EUR/USD')
        btn6 = types.InlineKeyboardButton('RUB/EUR', callback_data='RUB/EUR')
        btn7 = types.InlineKeyboardButton('OTHER', callback_data='OTHER')
        buttons2.add(btn1, btn2, btn3, btn4, btn5, btn6, btn7)
        bot.send_message(message.chat.id, 'Выберите валютную пару', reply_markup=buttons2)
    else:
        bot.send_message(message.chat.id, 'Ошибка. Число должно быть больше нуля', reply_markup=buttons)
        bot.register_next_step_handler(message, summ)
    
@bot.callback_query_handler(func=lambda call: True)
def callback_data(callback_data):
    callback_data_values = callback_data.data.upper().split('/')
    res = curency.convert(amount, callback_data_values[0], callback_data_values[1])
    bot.send_message(callback_data.message.chat.id, f'Результат: {res}. Можете снова вписать сумму и валютную парую')
    bot.register_next_step_handler(callback_data.message, summ)
    

bot.polling(non_stop=True)
问题原因
  1. 汇率数据源缺失RUB数据:currency_converter库默认使用欧洲央行(ECB)的数据源,该数据源不包含俄罗斯卢布(RUB)的汇率数据,尝试转换到RUB时会触发ValueError,而代码未添加异常捕获逻辑,直接导致机器人崩溃。
  2. 未处理OTHER按钮回调:点击OTHER按钮时,callback_data.data为OTHER,用split('/')分割后得到长度为1的列表,取callback_data_values[1]会触发索引越界错误。
解决方案

1. 添加异常捕获与按钮逻辑处理

修改回调处理函数,覆盖异常场景与未配置按钮的情况:

@bot.callback_query_handler(func=lambda call: True)
def callback_data(callback_data):
    global amount
    data = callback_data.data.upper()
    chat_id = callback_data.message.chat.id
    
    # 处理未配置的OTHER按钮
    if data == 'OTHER':
        bot.send_message(chat_id, '该功能暂未配置,请选择其他货币对')
        bot.register_next_step_handler(callback_data.message, summ)
        return
    
    callback_data_values = data.split('/')
    # 校验货币对格式
    if len(callback_data_values) != 2:
        bot.send_message(chat_id, '无效的货币对格式')
        bot.register_next_step_handler(callback_data.message, summ)
        return
    
    try:
        # 转换结果保留两位小数,提升可读性
        res = round(curency.convert(amount, callback_data_values[0], callback_data_values[1]), 2)
        bot.send_message(chat_id, f'Результат: {res}. Можете снова вписать сумму и валютную парую')
    except ValueError as e:
        bot.send_message(chat_id, f'转换失败:{str(e)},请选择其他货币对')
    finally:
        bot.register_next_step_handler(callback_data.message, summ)

2. 切换支持RUB的数据源

若需要支持RUB汇率转换,可更换currency_converter的数据源(示例为公开免费数据源):

# 替换为包含RUB的数据源
curency = CurrencyConverter('https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/usd.json')

也可以使用支持更多货币的第三方库,比如forex-python替代currency_converter。

3. 优化全局变量使用

原代码中全局变量amount存在线程安全风险(telebot为多线程架构),建议改用bot.user_data存储用户会话数据:

def summ(message):
    try:
        amount = int(message.text.strip())
    except ValueError:
        bot.send_message(message.chat.id, 'Ошибка. Введите сумму(числовой формат)', reply_markup=buttons)
        bot.register_next_step_handler(message, summ)
        return
    
    if amount > 0:
        # 保存当前用户的金额到会话
        bot.user_data[message.chat.id] = {'amount': amount}
        buttons2 = types.InlineKeyboardMarkup(row_width=3)
        # ... 按钮创建逻辑不变
    else:
        # ... 错误处理不变

@bot.callback_query_handler(func=lambda call: True)
def callback_data(callback_data):
    chat_id = callback_data.message.chat.id
    # 从会话获取当前用户的金额
    amount = bot.user_data.get(chat_id, {}).get('amount', 0)
    if amount <= 0:
        bot.send_message(chat_id, '请先输入有效的金额')
        bot.register_next_step_handler(callback_data.message, summ)
        return
    # ... 后续逻辑不变

内容的提问来源于stack exchange,提问作者В Не

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 22:14:55