Discord.py中Reporter Cog重复加载致任务重复执行问题排查
Discord.py 每日报告Cog重复加载问题排查与解决
问题核心原因
discord.py 并不会阻止同名Cog重复加载——只要调用bot.add_cog(),不管Cog实例的name是否重复,都会执行加载逻辑。虽然bot.cogs字典里的同名键会被后添加的实例覆盖,但之前加载的Cog实例中的定时任务仍然会独立运行,这就是「DO SOMETHING」重复执行的根本原因。
常见触发场景:
on_ready事件可能被多次触发(比如机器人重连时),如果没做初始化判断,会重复执行Cog加载逻辑- 数据库中存在重复的报告记录(比如添加报告时未做去重),重启后读取到多条相同ID+时间的记录,每条记录都加载一次Cog
具体解决办法
1. 限制on_ready仅执行一次初始化
给Bot实例加个标记,避免重连时重复初始化:
class MyBot(commands.Bot): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._is_initialized = False async def on_ready(self): if self._is_initialized: return # 此处执行数据库读取、Cog加载逻辑 self._is_initialized = True
2. 用报告ID追踪已加载的Cog
不要仅依赖Cog名称,改用报告ID作为唯一标识,维护一个字典记录已加载的实例:
# 在Bot类初始化时定义 self.active_reports = {} # 加载Cog前的检查逻辑 report_id = 从数据库读取的报告ID if report_id not in self.active_reports: cog_instance = DailyReportCog(report_id, report_time) await self.add_cog(cog_instance) self.active_reports[report_id] = cog_instance
3. 清理数据库重复记录
- 添加报告时,先校验数据库中是否已存在相同ID+时间的记录,避免重复写入
- 从数据库读取记录时,先做去重处理(比如按报告ID分组,只保留最新一条)
4. 加载新Cog前卸载旧实例(可选)
如果需要更新已存在的报告任务,先卸载旧Cog再加载新的:
if report_id in self.active_reports: old_cog = self.active_reports[report_id] await self.remove_cog(old_cog.qualified_name) new_cog = DailyReportCog(report_id, updated_report_time) await self.add_cog(new_cog) self.active_reports[report_id] = new_cog
内容的提问来源于stack exchange,提问作者Mihail Hurmuzov
相关产品推荐
相关产品推荐

