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

discord.py中bot.dispatch()无法正确触发Cog.listener()监听问题

discord.py 自定义newsong事件不触发问题排查

核心问题原因

  • 动态创建的audio_handler实例未完成Cog注册:discord.py框架下,被@commands.Cog.listener()标记的事件监听器,只有在Cog实例通过bot.add_cog()正式注册到Bot后,才会被加入Bot的事件回调队列。你当前仅在music_cog的server_list字典中存储了手动实例化的audio_handler对象,从未走Cog注册流程,Bot完全感知不到该Cog下的监听器存在,因此事件派发时不会触发对应回调,也不会抛出任何参数相关的错误。
  • 事件派发传参与监听器签名不匹配:你在play_music方法中调用dispatch时传入了3个位置参数self, ctx, title,但Cog内部的事件监听器第一个参数self是Cog实例自身,会在事件触发时由框架自动注入,不需要手动传入。多传的参数会导致监听器调用时参数数量不匹配,即便完成Cog注册也会触发调用异常。

修复步骤

  1. 动态创建audio_handler实例后,立刻调用add_cog完成注册,修改music_cog下play命令的逻辑:
@commands.command(name="play", aliases=["p","playing"], help="Plays a selected song from youtube")
async def play(self, ctx, *args):
    guild_key = str(ctx.guild.id)
    if guild_key not in self.server_list:
        audio_instance = audio_handler(self.bot)
        self.server_list[guild_key] = audio_instance
        # 注册Cog,激活内部的事件监听器
        await self.bot.add_cog(audio_instance)
    target_handler = self.server_list[guild_key]
    await target_handler.play(target_handler, ctx, *args)
  1. 修正事件派发的传参,移除多余的self参数:
# 原错误写法:self.bot.dispatch('newsong', self, ctx, self.music_queue[0][0]['title'])
# 修正后仅传入监听器除self外需要的业务参数
self.bot.dispatch('newsong', ctx, self.music_queue[0][0]['title'])
  1. 可选优化:如果业务逻辑包含音频实例销毁流程(比如语音频道闲置自动断开),销毁实例前调用await self.bot.remove_cog(target_handler.qualified_name)移除对应Cog,避免无效Cog长期占用内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:09:22