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

使用TeleBot的callback_query_handler双过滤器存状态遇NoneType错误

问题:TeleBot callback_query_handler中使用state过滤器时,retrieve_data返回None导致TypeError

在使用pyTelegramBotAPI的callback_query_handler时,同时设置func和自定义state过滤器存储状态,触发TypeError: 'NoneType' object does not support item assignment,报错行是data['model'] = call.data,不清楚为什么data是NoneType。

相关代码:

...
state_storage = StateMemoryStorage()

MODELS = ['ROAD', 'SPORTTOURIST']
MARKS = ['YAMAHA', 'HONDA']

class MyStates(StatesGroup):
    model = State()
    mark = State()

def models_motorcycle():
    return telebot.types.InlineKeyboardMarkup(
        keyboard=[
            [
                telebot.types.InlineKeyboardButton(MODELS[0], callback_data=MODELS[0]),
                telebot.types.InlineKeyboardButton(MODELS[1], callback_data=MODELS[1]),
            ]
        ]
    )

@bot.message_handler(commands=['start'])
def start_filter(message):
    bot.set_state(message.from_user.id, MyStates.model, message.chat.id)
    bot.send_message(message.chat.id, 'Select motorcycle model', reply_markup=models_motorcycle())


@bot.callback_query_handler(func=lambda call: call.data in MODELS, state=MyStates.model)
def callback_query_model(call):
    bot.set_state(call.from_user.id, MyStates.mark, call.message.chat.id)
    with bot.retrieve_data(call.message.from_user.id, call.message.chat.id) as data:
        # print(f'trying to save model data {call.data}')
        data['model'] = call.data
    bot.send_message(call.message.chat.id, 'Select motorcycle mark', reply_markup=marks_motorcycle())

错误原因

你在回调函数里先切换了状态(bot.set_state(..., MyStates.mark)),然后再调用retrieve_data(),此时retrieve_data默认获取的是当前活跃状态(也就是刚切换的MyStates.mark)的数据,但这个新状态还没有初始化任何数据,所以返回None,导致赋值时抛出错误。


修复方案

有两种可行的修复方式:

方式1:先保存数据,再切换状态

调整代码顺序,先获取当前状态(MyStates.model)的数据并保存,之后再切换到新状态:

@bot.callback_query_handler(func=lambda call: call.data in MODELS, state=MyStates.model)
def callback_query_model(call):
    # 先获取当前状态(model)的数据并保存
    with bot.retrieve_data(call.from_user.id, call.message.chat.id) as data:
        data['model'] = call.data
    # 再切换到mark状态
    bot.set_state(call.from_user.id, MyStates.mark, call.message.chat.id)
    bot.send_message(call.message.chat.id, 'Select motorcycle mark', reply_markup=marks_motorcycle())

方式2:retrieve_data时指定要获取的状态

如果需要在切换状态后获取之前状态的数据,可以在retrieve_data中指定state参数:

@bot.callback_query_handler(func=lambda call: call.data in MODELS, state=MyStates.model)
def callback_query_model(call):
    bot.set_state(call.from_user.id, MyStates.mark, call.message.chat.id)
    # 指定获取MyStates.model状态下的数据
    with bot.retrieve_data(call.from_user.id, call.message.chat.id, state=MyStates.model) as data:
        data['model'] = call.data
    bot.send_message(call.message.chat.id, 'Select motorcycle mark', reply_markup=marks_motorcycle())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 07:05:19