Discord bot自定义前缀功能get_prefix异步函数触发KeyError报错
问题原因
本次报错为KeyError,核心原因是get_prefix函数尝试从JSON文件中读取不存在的服务器ID对应的前缀值,常见触发场景如下:
- 该自定义前缀功能上线前,Bot已经加入了对应服务器,
on_guild_join事件从未触发,JSON文件中没有写入该服务器的ID记录 - Bot收到了私信频道的消息,此时
message.guild为None,无法匹配到有效服务器ID - 存储前缀的JSON文件被手动修改或意外损坏,丢失了对应服务器的记录
- 代码中路径写法存在转义问题,Windows环境下反斜杠
\会被识别为转义符,可能导致文件读取异常
解决方案
按以下步骤修改代码即可解决问题:
- 修复路径写法,使用原始字符串避免转义问题
- 修改
get_prefix函数,新增私信场景处理、不存在的服务器ID自动补全逻辑 - 新增启动时前缀记录补全逻辑,覆盖功能上线前已加入的旧服务器
- 优化
on_guild_remove逻辑,避免删除不存在的记录时报错
完整修改后的核心代码片段
1. 前置依赖(可选,用于自动创建存储文件夹)
import os # 启动前确保存储文件夹存在 os.makedirs(r'storage', exist_ok=True)
2. 修改get_prefix函数
async def get_prefix(client, message): # 处理私信场景,无服务器时返回默认前缀 if not message.guild: return '.' with open(r'storage\pp.json', 'r') as f: prefixes = json.load(f) guild_id = str(message.guild.id) # 服务器ID不存在时自动写入默认前缀 if guild_id not in prefixes: prefixes[guild_id] = '.' with open(r'storage\pp.json', 'w') as f: json.dump(prefixes, f, indent=4) return prefixes[guild_id]
3. 新增启动时初始化逻辑
@Bot.event async def on_ready(): with open(r'storage\pp.json', 'r') as f: prefixes = json.load(f) # 补全所有已加入服务器的前缀记录 for guild in Bot.guilds: guild_id = str(guild.id) if guild_id not in prefixes: prefixes[guild_id] = '.' with open(r'storage\pp.json', 'w') as f: json.dump(prefixes, f, indent=4) print('Bot启动完成,前缀记录已同步')
4. 优化on_guild_remove逻辑
@Bot.event async def on_guild_remove(guild): with open(r'storage\pp.json', 'r') as f: prefixes = json.load(f) # 第二个参数为默认值,记录不存在时不会抛出KeyError prefixes.pop(str(guild.id), None) with open(r'storage\pp.json', 'w') as f: json.dump(prefixes, f, indent=4) print(f'{guild.id} Left')
额外优化建议
如果你的Bot服务器数量较多,频繁读写JSON文件会有性能问题,可以将前缀记录缓存到内存字典中,仅在修改、启动、关闭时同步到JSON文件,运行效率会更高。
内容的提问来源于stack exchange,提问作者bat beat
相关产品推荐
相关产品推荐

