You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python开发Discord bot触发IndexError列表索引越界报错求助

Discord机器人start命令触发IndexError问题

以下是问题涉及的原始代码:

@bot.command()
async def start(ctx):
    edit = []
    with open("wallet.json", "w") as file:
        for obj in file:
            dict = json.load(obj)
            edit.append(dict)

    userid = []
    for player in edit:
        userid.append(str(player["id"]))

    user = str(ctx.author.id)
    if userid.count(user) > 0:
        await ctx.reply("You already have an account")
    else:
        embed = nextcord.Embed(title = "Welcome to the Kingdoms of Sulphae!", description = "Sulphae is a place where people can grind for resources, conquer other factions, and become the greatest king to ever exist! Enjoy your stay!")
        embed.set_footer(text = "Made by Energia360, a really pog dude who decided to dedicate his summer break to making a Discord bot")
        await ctx.send(embed = embed)
        userid.append(user)

        edit[userid.index(user)]["id"] = user
        edit[userid.index(user)]["gold"] = 0
        edit[userid.index(user)]["fyre"] = 0
        edit[userid.index(user)]["faction"] = None

    json.dump(edit, file)

问题现象

  • 使用Python开发Discord机器人时运行上述代码,当前wallet.json文件为空,代码执行到edit[userid.index(user)]["id"] = user位置时触发IndexError: list index out of range报错。

调试记录

  • 第一次调试:添加print()语句输出userid.index(user)的返回值为0,该索引数值本身不存在超出范围的问题,初步推测问题出在JSON字典键访问环节。
  • 第二次调试:将userid.index(user)的返回值提前存入独立变量再调用,报错依旧存在,进一步怀疑是键"id"的访问操作触发错误。
错误根因

索引越界和字典键访问没有任何关系,是三个基础逻辑错误导致的:

  1. 文件打开模式错误:读取wallet.json时使用了"w"(写入覆盖模式)打开文件,该模式会直接清空文件内所有原有内容,后续遍历文件读取JSON数据的逻辑完全不会执行,edit列表从初始化后就一直是空列表。
  2. 新用户数据未追加到edit列表:判断用户不存在时,只把新用户ID追加到了userid列表,根本没有给edit列表添加对应的新用户字典。此时userid长度比edit多1,拿到新用户ID在userid里的索引0去访问长度为0的空列表edit,必然触发索引越界。
  3. 文件作用域错误:json.dump(edit, file)写在with open()的代码块外面,此时文件对象已经被自动关闭,就算前面逻辑跑通,写入JSON的步骤也会报错。
修复方案
  1. 读取JSON文件时使用"r"(只读)模式,文件不存在或者内容为空时,直接初始化edit为空列表即可。
  2. 新用户注册时,先构造好新用户的字典数据,追加到edit列表后再做后续处理。
  3. 写入JSON时重新以"w"模式打开文件,把更新后的edit列表写入,不要在with块外操作已关闭的文件对象。
  4. 不要用dict做变量名,会覆盖Python内置的dict类型。

修复后的参考代码:

import os
import json
import nextcord

@bot.command()
async def start(ctx):
    edit = []
    # 钱包文件存在且有内容时才读取
    if os.path.exists("wallet.json") and os.path.getsize("wallet.json") > 0:
        with open("wallet.json", "r", encoding="utf-8") as file:
            edit = json.load(file)

    userid = [str(player["id"]) for player in edit]
    user = str(ctx.author.id)
    
    if user in userid:
        await ctx.reply("You already have an account")
        return
    
    # 新用户直接构造数据追加到edit列表
    new_user = {
        "id": user,
        "gold": 0,
        "fyre": 0,
        "faction": None
    }
    edit.append(new_user)

    embed = nextcord.Embed(
        title = "Welcome to the Kingdoms of Sulphae!", 
        description = "Sulphae is a place where people can grind for resources, conquer other factions, and become the greatest king to ever exist! Enjoy your stay!"
    )
    embed.set_footer(text = "Made by Energia360, a really pog dude who decided to dedicate his summer break to making a Discord bot")
    await ctx.send(embed = embed)

    # 写入更新后的数据
    with open("wallet.json", "w", encoding="utf-8") as file:
        json.dump(edit, file, indent=2, ensure_ascii=False)

额外优化点:用user in userid替代userid.count(user) > 0判断用户是否存在,执行效率更高。

内容的提问来源于stack exchange,提问作者Energia360

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:27:16