Discord.py等级系统开发求助:JSON错误与数据迁移等问题
解决JSONDecodeError & 等级系统存储+MEE6迁移指南
先搞定JSONDecodeError
你遇到的错误大概率是第一次运行时JSON文件未创建,或是文件为空导致解析失败。直接给你改段能处理空文件/不存在场景的代码:
import json import os # 读取用户数据的封装函数 def load_users(): if not os.path.exists('users.json'): # 文件不存在时初始化空字典并保存 with open('users.json', 'w') as f: json.dump({}, f) return {} with open('users.json', 'r') as f: try: return json.load(f) except json.JSONDecodeError: # 文件为空或格式错误时重置为空字典 with open('users.json', 'w') as f: json.dump({}, f) return {} # 保存用户数据的封装函数 def save_users(users): with open('users.json', 'w') as f: json.dump(users, f, indent=4)
把你原来读取JSON的逻辑换成这个函数调用,比如在on_message事件里:
@client.event async def on_message(message): if message.author.bot: return users = load_users() # 后续XP计算、等级提升逻辑... save_users(users)
等级数据存储方案怎么选?
1. JSON文件(适合小服务器)
- 优点:零配置、上手快,直接用Python内置
json模块操作,适合成员数≤100的小型服务器。 - 缺点:并发写入易冲突、数据量变大后读写变慢,无法实现复杂查询(比如按等级排序、筛选特定区间用户)。
2. 数据库(推荐中大型服务器)
如果服务器成员多,或后续要加复杂功能,直接上数据库:
- SQLite:入门首选,无需额外安装服务,Python自带
sqlite3模块,单文件存储,适配单进程Discord Bot。 - PostgreSQL/MySQL:若Bot需要分布式部署或处理高并发,选这类数据库,支持事务、复杂查询,扩展性更强。
给个SQLite的极简示例:
import sqlite3 # 初始化数据库连接 conn = sqlite3.connect('levels.db') c = conn.cursor() # 创建用户等级表(不存在则创建) c.execute('''CREATE TABLE IF NOT EXISTS users (user_id INTEGER PRIMARY KEY, guild_id INTEGER, xp INTEGER, level INTEGER)''') conn.commit() # 更新/插入用户数据 def update_user(user_id, guild_id, xp, level): c.execute('''INSERT OR REPLACE INTO users (user_id, guild_id, xp, level) VALUES (?, ?, ?, ?)''', (user_id, guild_id, xp, level)) conn.commit() # 查询用户数据 def get_user(user_id, guild_id): c.execute('SELECT xp, level FROM users WHERE user_id = ? AND guild_id = ?', (user_id, guild_id)) return c.fetchone() or (0, 1)
从MEE6迁移数据的最佳方式
用mee6_py_api的话,步骤清晰,注意确保Bot有足够权限,且目标服务器MEE6排行榜未设权限限制:
1. 安装依赖
pip install mee6-py-api
2. 批量获取MEE6服务器等级数据
from mee6_py_api import API async def import_mee6_data(guild_id): api = API() all_users = [] page = 0 # 分页获取数据(MEE6默认最多显示前1000名) while True: try: data = await api.get_guild_leaderboard(guild_id, page=page) if not data['players']: break all_users.extend(data['players']) page += 1 except Exception as e: print(f"获取数据出错: {e}") break return all_users
3. 导入到你的存储系统
比如导入到JSON文件:
async def main(): guild_id = 1234567890 # 替换成你的服务器ID mee6_users = await import_mee6_data(guild_id) users = load_users() for user in mee6_users: user_id = user['id'] users[user_id] = { 'xp': user['xp'], 'level': user['level'], 'guild_id': guild_id } save_users(users) print(f"成功导入{len(mee6_users)}名用户的等级数据") # 在Bot启动时执行迁移,比如在on_ready事件中: @client.event async def on_ready(): print(f'Logged in as {client.user}') await main()
注意事项
- 若服务器MEE6排行榜有权限限制,无法通过API获取数据,可让管理员调整MEE6权限,或手动导出MEE6的CSV数据再导入。
- 迁移完成后,测试你的Bot XP计算逻辑,确保和MEE6的增长规则匹配(或按需求自定义规则)。
内容的提问来源于stack exchange,提问作者DRags
相关产品推荐
相关产品推荐

