基于Discord.py的用户等级系统无终端报错但JSON数据不更新问题咨询
Discord.py等级系统users.json不更新问题排查
- 第一类:语法笔误(直接导致代码无法运行)
update_data函数内等级初始化行存在右括号多写、引号配对错误的问题,原代码为users[user.id]]'level"] = 1,正确写法为users[str(user.id)]["level"] = 1level_up函数内调用ctx.send(channel, 'xxx')存在变量未定义、方法调用语法错误的问题:此处无ctx上下文对象,且向指定频道发消息的正确写法为channel.send('内容'),触发升级逻辑时会直接抛出异常中断流程
- 第二类:逻辑设计错误(导致数据写入失效或损坏)
on_member_join事件中读取users.json时未将json.load的返回值赋值给users变量,代码中仅执行了json.load(f)就直接使用未定义的users变量,触发事件时会直接抛出未定义变量的错误,中断后续写入流程。正确写法应为users = json.load(f)update_data函数无返回值,但on_member_join事件中使用users = await update_data(users, member)接收返回值,会直接将原读取到的users字典覆盖为None,后续写入文件时实际存储的是无效内容。由于字典是可变对象,函数内修改会直接作用于原对象,无需额外赋值,要么去掉赋值操作,要么在update_data末尾添加return users- 未将Discord用户ID转为字符串就作为字典键,JSON序列化时会自动将整数键转为字符串,后续读写时会出现键类型不匹配的问题,所有用
user.id作为键的位置统一替换为str(user.id)即可解决
- 第三类:冗余设计(引发并发写入冲突)
- 现有逻辑在
on_message末尾、level_up函数内部都存在json.dump写入users.json的操作,多用户同时发消息时容易出现文件读写竞争,导致写入失败或文件内容损坏。应删除level_up内部的写入逻辑,统一在所有数据修改完成后执行一次写入操作
- 现有逻辑在
- 第四类:客户端配置缺失(导致事件根本不触发)
Discord.py 2.0版本后需要在初始化客户端时显式开启所需的intents:如果没有开启membersintent,on_member_join事件永远不会触发;如果没有开启message_contentintent,on_message事件也无法正常获取用户消息内容,直接导致所有等级逻辑完全不执行,终端自然不会输出报错。
修正后核心参考代码
import json import discord from discord.ext import commands # 初始化客户端,按需开启所需intents intents = discord.Intents.default() # 开启成员相关事件权限 intents.members = True # 开启读取消息内容权限 intents.message_content = True client = commands.Bot(command_prefix='!', intents=intents) async def update_data(users, user): user_key = str(user.id) if user_key not in users: users[user_key] = { "experience": 0, "level": 1 } return users async def add_experience(users, user, exp): user_key = str(user.id) users[user_key]["experience"] += exp async def level_up(users, user, channel): user_key = str(user.id) experience = users[user_key]['experience'] lvl_start = users[user_key]['level'] lvl_end = int(experience ** (1/4)) if lvl_start < lvl_end: await channel.send(f'{user.mention} has leveled up to level {lvl_end}') users[user_key]["level"] = lvl_end @client.event async def on_member_join(member): # 兼容文件不存在或内容为空的异常场景 try: with open("users.json", "r") as f: users = json.load(f) except (FileNotFoundError, json.JSONDecodeError): users = {} await update_data(users, member) with open("users.json", "w") as f: # indent参数让JSON文件格式化更易读 json.dump(users, f, indent=2) @client.event async def on_message(message): # 忽略机器人自身消息,避免无效计数 if message.author.bot: return try: with open("users.json", "r") as f: users = json.load(f) except (FileNotFoundError, json.JSONDecodeError): users = {} await update_data(users, message.author) await add_experience(users, message.author, 5) await level_up(users, message.author, message.channel) # 所有数据修改完成后统一写入一次 with open("users.json", "w") as f: json.dump(users, f, indent=2) # 启动机器人时替换为自身机器人Token # client.run("你的机器人Token")
内容的提问来源于stack exchange,提问作者demon_ven
相关产品推荐
相关产品推荐

