Discord.py机器人离线后加服触发KeyError的修复方案求助
The issue you're facing happens because when your bot is offline, it can't trigger the on_guild_join event—so any guilds added during that time don't get their ID saved to prefixes.json. When the bot restarts, trying to access a guild ID that's missing from the file throws a KeyError. Here's how to fix this with a combination of error handling and startup syncing:
1. Add Try-Except to get_prefix (Immediate Error Handling)
Modify your get_prefix function to catch the KeyError, add the missing guild to the JSON file, and return the default prefix. This acts as a safety net whenever the bot encounters a guild not in the file:
import json from discord.ext import commands def get_prefix(client, message): # Handle DMs (no guild ID) if not message.guild: return 's!' # Default prefix for DMs with open('prefixes.json', 'r') as f: prefixes = json.load(f) try: return prefixes[str(message.guild.id)] except KeyError: # Guild not found in file—add it with default prefix prefixes[str(message.guild.id)] = 's!' with open('prefixes.json', 'w') as f: json.dump(prefixes, f, indent=4) return 's!' client = commands.Bot(command_prefix=get_prefix)
2. Sync Guilds on Bot Startup
Add an on_ready event to automatically check all guilds the bot is part of when it starts up. This ensures any guilds added while offline get added to prefixes.json immediately on restart:
@client.event async def on_ready(): print(f'Logged in as {client.user.display_name}!') # Load existing prefixes with open('prefixes.json', 'r') as f: prefixes = json.load(f) # Check every guild the bot is in for guild in client.guilds: guild_id_str = str(guild.id) if guild_id_str not in prefixes: prefixes[guild_id_str] = 's!' print(f"Added missing guild: {guild.name} ({guild.id})") # Save the updated prefixes with open('prefixes.json', 'w') as f: json.dump(prefixes, f, indent=4) print("Successfully synced prefixes with all guilds!")
3. Keep Your Existing Guild Events
Your on_guild_join and on_guild_remove events are already correct for handling guild additions/removals while the bot is online—keep them as is:
@client.event async def on_guild_join(guild): with open('prefixes.json', 'r') as f: prefixes = json.load(f) prefixes[str(guild.id)] = 's!' with open('prefixes.json' , 'w') as f: json.dump(prefixes, f, indent = 4 ) @client.event async def on_guild_remove(guild) : with open('prefixes.json' , 'r') as f: prefixes = json.load(f) prefixes.pop(str(guild.id)) with open('prefixes.json' , 'w') as f: json.dump(prefixes, f, indent = 4 )
Why This Works
- The
try-exceptinget_prefixcatches any missing guild IDs on the fly, preventing KeyErrors and ensuring the bot responds correctly. - The
on_readysync runs once when the bot starts, making sure all guilds the bot is currently part of are in the prefixes file—even those added while offline. - Your existing events handle real-time guild changes while the bot is online.
内容的提问来源于stack exchange,提问作者Ares

