You need to enable JavaScript to run this app. Discord.py Rewrite使用Cog触发命令重复发消息且数量递增问题求助
优惠活动
大模型
产品
解决方案
定价
更多

Discord.py Rewrite使用Cog触发命令重复发消息且数量递增问题求助

问题核心原因

你观测到的“每次触发命令发送的消息数逐次多1”的现象,核心是同一个Cog被反复重复挂载到bot实例上,没有清理旧的实例残留。
每个被成功挂载到bot上的Cog,都会独立注册自己携带的命令、独立绑定自己的事件监听器。当bot上累计存在N个相同的currencyCog实例时,一次命令触发就会同时执行N次test命令的发送逻辑,对应发出N条消息;每重复加载一次Cog,N的值就会+1,和你观察到的规律完全匹配。

对应修复操作

  • 修正主程序里的Cog加载逻辑,避免重复挂载
    加载Cog前先检查是否已存在同名Cog,存在就先卸载旧实例再加载新实例,示例代码:
    # 主程序中的Cog加载逻辑
    async def on_ready():
        if "currencyCog" in bot.cogs:
            await bot.remove_cog("currencyCog")
        await bot.add_cog(currencyCog(bot))
    
  • 调整Cog类内的变量初始化位置,避免全局污染
    你当前把global currency声明和currency字典的读取逻辑直接写在类定义的顶层作用域,这里存在两个问题:
    1. global关键字仅能在函数/方法作用域内生效,放在类顶层作用域没有任何变量声明效果,属于无效写法
    2. 直接在类顶层读取json文件的逻辑,会在类被定义时就执行,Cog被重复加载时会反复覆盖全局的currency对象,加剧数据异常
      正确的写法是把数据初始化移到__init__方法中,用类实例属性替代全局变量:
    class currencyCog(commands.Cog):
        def __init__(self, bot):
            self.bot = bot
            # 将原类块中的json读取逻辑移至此处
            with open('cogs/data/currency.json') as f:
                self.currency = json.load(f)
    
        def _save(self):
            # 所有原引用全局currency的位置,改为引用self.currency
            with open('cogs/data/currency.json', 'w+') as f:
                json.dump(self.currency, f)
    
        async def new_user(self, id:int):
            self.currency[str(id)] = {
                "cash": 100,
                "multi": 1,
                "upgrades": {
                    "click_max": 100
                },
                "items": {
                    "beginner-crate": 1
                }
            }
            self._save()
            user = self.bot.get_user(id)
            await user.send('message')
    
        @commands.Cog.listener()
        async def on_command(self, ctx):
            id = ctx.author.id
            if str(id) in self.currency:
                pass
            else:
                await self.new_user(id)
    
        @commands.command()
        async def test(self, ctx):
            await ctx.send('beep')
    
  • 调整本地调试的运行方式
    你当前用Sublime Text的默认Python构建反复触发运行的方式,很容易出现旧的bot进程未完全退出、WebSocket连接未完全断开就启动新实例的问题,导致Cog的监听逻辑残留。调试时需要等旧进程完全退出、控制台打印出连接断开的日志后,再启动新的运行实例。

排查技巧:如果上述调整后仍然存在重复消息的问题,可以在on_ready事件里打印len(bot.cogs)和已加载Cog的列表,确认当前bot上挂载的Cog数量是否和预期一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.29 11:54:03