You need to enable JavaScript to run this app. 基于Discord.py的用户等级系统无终端报错但JSON数据不更新问题咨询
优惠活动
大模型
产品
解决方案
定价
更多

基于Discord.py的用户等级系统无终端报错但JSON数据不更新问题咨询

Discord.py等级系统users.json不更新问题排查
  • 第一类:语法笔误(直接导致代码无法运行)
    • update_data函数内等级初始化行存在右括号多写、引号配对错误的问题,原代码为users[user.id]]'level"] = 1,正确写法为users[str(user.id)]["level"] = 1
    • level_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:如果没有开启members intent,on_member_join事件永远不会触发;如果没有开启message_content intent,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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.30 00:45:07