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字典的读取逻辑直接写在类定义的顶层作用域,这里存在两个问题:global关键字仅能在函数/方法作用域内生效,放在类顶层作用域没有任何变量声明效果,属于无效写法- 直接在类顶层读取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
相关产品推荐
相关产品推荐

