Discord卡牌收集机器人Python IndexError索引越界问题求助
问题排查与修复方案
核心错误原因
你代码里的random.choices(cardPathList, cardRarity)没有指定k=3参数,该函数默认仅返回1个元素,导致cardsToDrop列表长度为1,后续访问cardsToDrop[1]和cardsToDrop[2]时触发IndexError。
分步修复
1. 修复随机选卡逻辑
修改random.choices调用,明确指定k=3,确保返回3张卡牌:
cardsToDrop = random.choices(cardPathList, weights=cardRarity, k=3)
注意:
random.choices的第二个参数是weights(权重),建议显式命名参数,避免歧义。
2. 处理卡牌数量不足的边界情况
如果数据库中Cards表的卡牌总数少于3张,当前的while True循环会无限执行,因为永远无法选出3张不重复的卡牌。需要添加前置判断:
cardPathList = await query("SELECT filename FROM Cards ORDER BY cardname", cardDBCommand) if len(cardPathList) < 3: await ctx.send("数据库中卡牌数量不足3张,无法执行drop操作!") return
3. 修复SQL注入风险(重要)
当前用f-string拼接SQL语句存在严重的SQL注入漏洞,必须改用参数化查询。以获取卡牌名称的语句为例:
# 替换原有的cardNames查询语句 sql = "SELECT cardname FROM Cards WHERE filename IN (?, ?, ?)" cardNames = await query(sql, cardDBCommand, params=(cardsToDrop[0], cardsToDrop[1], cardsToDrop[2]))
注意:需要确认你的
query函数支持接收params参数来处理参数化查询,如果不支持,需根据使用的数据库驱动(如sqlite3、asyncpg等)调整参数传递方式。
4. 其他潜在问题修复
- 代码中
UPDATE Users SET lastgrab = ...是笔误,应改为lastdrop,和数据库字段名保持一致。 - 重复的用户判断逻辑可简化,减少冗余SQL查询。
修复后的核心代码片段
# ... 前面的用户逻辑 ... cardPathList = await query("SELECT filename FROM Cards ORDER BY cardname", cardDBCommand) if len(cardPathList) < 3: await ctx.send("数据库中卡牌数量不足3张,无法执行drop操作!") return cardRarity = await query("SELECT rarity FROM Cards ORDER BY cardname", cardDBCommand) cardsToDrop = [] while True: cardsToDrop = random.choices(cardPathList, weights=cardRarity, k=3) if len(set(cardsToDrop)) == 3: break # 参数化查询获取卡牌名称 sql = "SELECT cardname FROM Cards WHERE filename IN (?, ?, ?)" cardNames = await query(sql, cardDBCommand, params=(cardsToDrop[0], cardsToDrop[1], cardsToDrop[2])) imageCreation(cardsToDrop, GREY, os.path.abspath("Temp/drop.png"))
内容的提问来源于stack exchange,提问作者ByRedox
相关产品推荐
相关产品推荐

