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)
问题原因
- 汇率数据源缺失RUB数据:
currency_converter库默认使用欧洲央行(ECB)的数据源,该数据源不包含俄罗斯卢布(RUB)的汇率数据,尝试转换到RUB时会触发ValueError,而代码未添加异常捕获逻辑,直接导致机器人崩溃。 - 未处理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,提问作者В Не
相关产品推荐
相关产品推荐

