整数输入验证问题:机器人二次尝试后无响应的修复方法
问题
我的机器人要求用户输入整数,有两种规则:
- 整数需满足
>0 且 <31(对应month类型) - 整数需满足
>0 且 <185(对应every_few_days类型)
写了输入验证代码后,机器人在用户第二次尝试输入时就无响应,该怎么修复?
当前涉及的代码如下:
主函数接收用户输入
async def _save_data(user_data: str, state: FSMContext, type: str): data = await state.get_data() user_id = data['user'] try: validate_date(user_data, type) except (InvalidDate, ValueError) as error: await bot.send_message(user_id, error) except Exception as e: await bot.send_message(user_id, messages.error_message.format(e)) else: ### saves to the DB
输入验证函数
def validate_date(user_date: str, record_type: str): match record_type: case 'month': try: if int(user_date) > 31 or int(user_date) <= 0: raise InvalidDate(messages.invalid_month_message) except ValueError: raise InvalidDate(messages.invalid_digits_message) case 'every_few_days': if int(user_date) > 185: raise InvalidDate(messages.invalid_days_message) case 'once': if datetime.strptime(user_date, "%Y-%m-%d").date() < datetime.today().date(): raise InvalidDate(messages.invalid_calendar_date)
日历发送函数(once场景功能正常)
async def receive_calendar_date(date: datetime, state: FSMContext, user_id: int): data = await state.get_data() date_to_save = '' try: validate_date(str(date), data['type']) except InvalidDate as e: await bot.send_message(user_id, e, reply_markup=await SimpleCalendar().start_calendar()) else: ### saves user's data
自定义异常类
class InvalidDate(Exception): pass
问题根源
every_few_days验证逻辑不全:只判断了输入大于185的情况,完全没处理输入<=0或者非整数的场景,这类输入会直接抛出ValueError,虽然主函数捕获了,但没有引导用户重新输入。- 输入错误后会话状态中断:主函数发送错误提示后,没有维持FSM的当前状态,导致机器人不再监听用户的下一次输入——而
once场景正常是因为错误后重新发送了日历组件,相当于主动维持了交互状态。 month分支的int转换重复:每次判断都调用int(user_date),既低效又可能重复触发异常。
修复步骤
1. 补全验证函数的逻辑漏洞
统一处理所有输入场景的校验,把非整数输入、边界值判断都覆盖到:
def validate_date(user_date: str, record_type: str): match record_type: case 'month': try: num = int(user_date) if not (0 < num < 31): raise InvalidDate(messages.invalid_month_message) except ValueError: raise InvalidDate(messages.invalid_digits_message) case 'every_few_days': try: num = int(user_date) if not (0 < num < 185): raise InvalidDate(messages.invalid_days_message) except ValueError: raise InvalidDate(messages.invalid_digits_message) case 'once': try: input_date = datetime.strptime(user_date, "%Y-%m-%d").date() if input_date < datetime.today().date(): raise InvalidDate(messages.invalid_calendar_date) except ValueError: # 可以新增一个日期格式错误的提示文案 raise InvalidDate("请输入正确的日期格式:YYYY-MM-DD")
2. 修改主函数,维持会话状态
捕获输入错误后,除了发送提示,还要让机器人继续停留在当前输入状态,等待用户重新输入(这里假设你的FSM状态名为Form.waiting_for_number,根据实际情况调整):
async def _save_data(user_data: str, state: FSMContext, type: str): data = await state.get_data() user_id = data['user'] try: validate_date(user_data, type) except InvalidDate as error: await bot.send_message(user_id, str(error)) # 关键:维持当前会话状态,让机器人继续接收用户输入 await state.set_state(Form.waiting_for_number) except Exception as e: await bot.send_message(user_id, messages.error_message.format(e)) await state.set_state(Form.waiting_for_number) else: # 执行保存到数据库的逻辑 await bot.send_message(user_id, "输入有效,已保存") await state.finish() # 完成输入后结束会话状态
3. 统一异常类型(可选)
把所有输入相关的错误都转换成InvalidDate异常,主函数只需处理这一种异常即可,减少冗余逻辑。
内容的提问来源于stack exchange,提问作者pizhlo
相关产品推荐
相关产品推荐

