Discord.py开发生日播报机器人触发Replit数据库KeyError及get_user问题
KeyError 直接触发原因
你在拆分生日存储字段时,多做了一次无意义的数据库查表操作:
- 数据库中对应字段的存储格式为
"bd043010" : "690738010903281734 310439746247589889",拆分字符串后splitX[0]为服务器ID,splitX[1]本身就是需要的用户ID,不需要再将其作为数据库键进行查询 - 错误代码段:
print(db[splitX[1]]) userId = int(db[splitX[1]])
这段代码尝试以拆分得到的用户ID为键读取数据库,而数据库中不存在任何键值对以该ID作为键,直接触发KeyError: 310439746247589889。
修正后代码:
userId = int(splitX[1])
现存逻辑bug清单
- 键存在判断逻辑错误:原代码
if "date_md" and "B_today" in db.keys():受Python运算符优先级影响,等价于判断「非空字符串"date_md"恒为真 + 仅校验"B_today"键是否存在」,完全没有检查date_md键是否存在,首次运行时极易触发未定义键读取异常。正确写法应为:if "date_md" in db.keys() and "B_today" in db.keys(): - 播报状态标记逻辑失效:原代码无论当天是否成功发送了播报消息,最后都会将
db["B_today"]设为True,且每次循环都会把存储的date_md对齐到当天日期,导致下一次循环触发时,程序会直接判定“今日播报已完成”,永远不会真正触发生日消息发送。 - 消息发送逻辑错误:你将存储寿星列表的空列表
B_days定义在服务器遍历循环内部,且每匹配到一个寿星就直接发送一次embed,最终同一个服务器每有一个寿星就会收到一条单独的播报消息,无法将当日所有寿星合并为同一条内容。 - 定时任务时间可靠性差:设置
hours=23.9的固定间隔循环会随运行时长累积产生时间漂移,遇到系统时间校准、夏令时切换、闰年跨天场景时,极易出现重复播报、漏报的问题。 - 空值风险无防护:直接通过
client.get_channel()获取播报通道时,如果机器人尚未完成缓存加载、被移出通道、权限不足,会返回None,后续执行发送消息操作时会直接触发属性错误。
可优化方向
- 重构定时触发逻辑:放弃固定间隔循环的设计,改为每次循环启动时先计算距离当日零点的剩余时长,等待到达零点后再执行生日检查流程,从根源上解决时间漂移问题。
- 简化数据存储结构:不要将服务器ID+用户ID拼接为长字符串存储,改为为每一条生日记录设置独立键(例如
bd_{日期}_{用户ID},值为对应的服务器ID),不需要手动拆分字符串,后续新增、修改、删除生日信息的逻辑也更易维护。 - 增加异常防护:发送消息前校验播报通道对象是否存在、当日寿星列表是否为空,列表为空时直接跳过发送流程,不要推送无内容的空embed。
- 修正状态标记逻辑:仅当当日所有播报消息都发送成功后,才将
B_today标记为True;如果发送中途出现异常,要将状态重置为未发送,等待下一次循环重试,避免因临时网络问题导致全天漏报。
内容的提问来源于stack exchange,提问作者Mr Mandude
相关产品推荐
相关产品推荐

