Discord.py读取warns.json时触发ValueError: not enough values to unpack报错的解决求助
Fixing the ValueError in Your Discord.py Warning Lookup Code
Let's break down what's going wrong and how to fix it step by step.
Why You're Getting This Error
Your current code has two key issues:
- Incorrect dictionary traversal: When you loop
for mod , reason, time, warn_id, warns in user_data, Python is only iterating over the keys of theuser_datadictionary (like"mod","reason", etc.). Each key is a string, so when you try to unpack it into 5 variables, Python tries to split the string into characters—hence the errornot enough values to unpack (expected 5, got 3)(since"mod"is 3 characters long). - Mismatched JSON structure: Your
warns.jsonstores most fields as single-element arrays (e.g.,"mod": [763339711988236328]), but your code expects to unpack them directly as individual values. Also, your total warning count calculation is wrong—len(user_data)gives you the number of fields in the dictionary (5), not the actual warning count stored in the"warns"key.
Solution 1: Work With Your Existing JSON Structure
Here's how to adjust your code to correctly read the data from your current warns.json:
import json from discord.ext import commands @commands.command() async def check_warns(ctx, a): with open("warns.json", "r") as f: data = json.load(f) user_id = str(a) # Handle users with no warnings if user_id not in data: await ctx.send("This user has no warnings.") return user_data = data[user_id] total_warns = user_data["warns"] await ctx.send(f"Total warnings: {total_warns}") # Iterate over each warning (using index since fields are arrays) for idx in range(total_warns): warn_id = user_data["warn_id"][idx] mod = user_data["mod"][idx] reason = user_data["reason"][idx] time = user_data["time"][idx] await ctx.send(f"ID: {warn_id}, mod: {mod}, reason: {reason}, time: {time}")
Solution 2: Refactor Your JSON for Easier Maintenance
Your current JSON structure isn't ideal for storing multiple warnings. A better approach is to store each warning as an object in an array. This makes looping simpler and scales better for users with multiple warnings.
Updated warns.json:
{ "836495228629417984": [ { "mod": 763339711988236328, "reason": "test", "time": "Friday, October 08 2021 @ 23:15:31 PM", "warn_id": 83299 } ] }
Corresponding Code:
import json from discord.ext import commands @commands.command() async def check_warns(ctx, a): with open("warns.json", "r") as f: data = json.load(f) user_id = str(a) if user_id not in data or not data[user_id]: await ctx.send("This user has no warnings.") return user_warns = data[user_id] await ctx.send(f"Total warnings: {len(user_warns)}") # Loop directly through each warning object for warn in user_warns: await ctx.send(f"ID: {warn['warn_id']}, mod: {warn['mod']}, reason: {warn['reason']}, time: {warn['time']}")
Key Takeaways
- Always check if a user exists in your JSON before accessing their data to avoid unexpected KeyErrors.
- When working with dictionaries, use explicit key access (
dict["key"]) instead of trying to unpack the dictionary directly in a loop. - For collections of items (like multiple warnings), use arrays of objects in JSON—it makes your code cleaner and more maintainable as you add more warnings over time.
内容的提问来源于stack exchange,提问作者LopeKinz
相关产品推荐
相关产品推荐

