Discord Bot仅执行最后一段代码问题求助
Discord Bot命令仅最后一个生效的问题解决
问题情况
之前正常运行的Discord Bot,重启后出现异常:只有最后一段代码对应的命令能正常执行——删除!slap的代码段后,只剩!punch命令可用;删除!punch代码段后,仅!help、!hello等前面的命令恢复。多次重新输入代码、修改函数都无法解决。
问题根源
你重复定义了多个@client.event async def on_message(message)事件处理函数。在Discord.py中,同一个事件(比如on_message)只能有一个生效的处理函数,最后注册的那个会覆盖之前所有的同名事件处理,这就是为什么只有最后一段代码的命令能工作。
解决方案
下面提供两种可行的修复方式:
方案1:合并所有逻辑到单个on_message事件
把所有命令的判断逻辑整合到同一个on_message函数中,让所有命令都能被依次检查执行:
# installed: discord api import discord import random from datetime import date from discord.ext import commands from discord.embeds import Embed from discord import colour TOKEN = '***********' intents = discord.Intents.all() intents.message_content = True client = discord.Client(intents=intents) @client.event async def on_ready(): print(f"Bot logged in as {client.user}") @client.event async def on_message(message): if message.author == client.user: return # 跳过机器人自己发的消息,避免重复处理 # !hello 命令 if message.content.lower().startswith('!hello'): await message.channel.send(f"Wassup, `{message.author}`") # !help 命令 elif message.content.lower().startswith('!help'): await message.channel.send(f"`{message.author}` \nHere are all my commands:\n \n!hello ~ greet the bot \n" f"!roll ~ the bot will give a random value between 1 and 100 \n" f"!day ~ the bot will give the date and time \n" f"!punch ~ the bot will send a punching gif ( not nsfw )\n" f"!slap ~ the bot will send a slapping gif\n" f"") # !roll 命令 elif message.content.lower().startswith('!roll'): number = str(random.randint(1, 100)) await message.channel.send('Your number is: ' + number) # !day 命令 elif message.content.lower().startswith('!day'): today = date.today() await message.channel.send(f"The local date today is {today}") # !punch 命令 elif message.content.lower().startswith('!punch'): punch_gifs = ['https://media.tenor.com/6Cp5tiRwh-YAAAAC/meme-memes.gif'] punch_names = ['Punched You'] embed = discord.Embed( colour=(discord.Colour.random()), description=f'{message.author.mention} {random.choice(punch_names)}' ) embed.set_image(url=(random.choice(punch_gifs))) await message.channel.send(embed=embed) # !slap 命令 elif message.content.lower().startswith('!slap'): slap_gifs = ['https://media.tenor.com/mNAs5CO1deIAAAAC/slap.gif'] slap_names = ['slapped you'] embed = discord.Embed( colour=(discord.Colour.random()), description=f'{message.author.mention} {random.choice(slap_names)}' ) embed.set_image(url=(random.choice(slap_gifs))) await message.channel.send(embed=embed) client.run(TOKEN)
方案2:使用commands框架(更规范的写法)
你已经导入了discord.ext.commands并创建了bot实例,建议用框架自带的命令装饰器来定义命令,不仅避免事件覆盖问题,代码结构也更清晰:
# installed: discord api import discord import random from datetime import date from discord.ext import commands from discord.embeds import Embed from discord import colour TOKEN = '***********' intents = discord.Intents.all() intents.message_content = True # 直接使用commands.Bot实例,不需要再创建discord.Client bot = commands.Bot(command_prefix='!', intents=intents) @bot.event async def on_ready(): print(f"Bot logged in as {bot.user}") # !hello 命令 @bot.command() async def hello(ctx): await ctx.send(f"Wassup, `{ctx.author}`") # !help 命令(可以自定义help内容,也可以用框架默认的) @bot.command() async def help(ctx): await ctx.send(f"`{ctx.author}` \nHere are all my commands:\n \n!hello ~ greet the bot \n" f"!roll ~ the bot will give a random value between 1 and 100 \n" f"!day ~ the bot will give the date and time \n" f"!punch ~ the bot will send a punching gif ( not nsfw )\n" f"!slap ~ the bot will send a slapping gif\n" f"") # !roll 命令 @bot.command() async def roll(ctx): number = str(random.randint(1, 100)) await ctx.send('Your number is: ' + number) # !day 命令 @bot.command() async def day(ctx): today = date.today() await ctx.send(f"The local date today is {today}") # !punch 命令 @bot.command() async def punch(ctx): punch_gifs = ['https://media.tenor.com/6Cp5tiRwh-YAAAAC/meme-memes.gif'] punch_names = ['Punched You'] embed = discord.Embed( colour=(discord.Colour.random()), description=f'{ctx.author.mention} {random.choice(punch_names)}' ) embed.set_image(url=(random.choice(punch_gifs))) await ctx.send(embed=embed) # !slap 命令 @bot.command() async def slap(ctx): slap_gifs = ['https://media.tenor.com/mNAs5CO1deIAAAAC/slap.gif'] slap_names = ['slapped you'] embed = discord.Embed( colour=(discord.Colour.random()), description=f'{ctx.author.mention} {random.choice(slap_names)}' ) embed.set_image(url=(random.choice(slap_gifs))) await ctx.send(embed=embed) bot.run(TOKEN)
说明
方案2更符合Discord.py的最佳实践,后续添加新命令也更方便,还能利用框架自带的错误处理、命令别名等功能。
内容的提问来源于stack exchange,提问作者xanebot
相关产品推荐
相关产品推荐

