如何在discord.py的Cog类中正确使用aioschedule解决参数报错问题
问题修复方案
核心问题原因
- 定时任务注册位置错误:直接写在类命名空间下的
schedule.every(5).seconds.do(ping)获取的是未绑定实例的ping方法,没有self上下文,调用时必然缺失参数 - 事件循环冲突:自定义的
while True调度循环会阻塞discord.py本身的事件循环,导致bot无法正常响应事件 - API调用错误:
self.client.send()是无效写法,discord.py中消息发送只能通过频道对象调用 - 循环任务未注册:
bot_test_clear方法没有添加@tasks.loop装饰器,直接调用start()会报错
修复后完整代码
import discord import os import asyncio from discord.ext import commands, tasks import aioschedule as schedule class Events(commands.Cog): def __init__(self, client): self.client = client @tasks.loop(hours=1) async def bot_test_clear(self): channel_bot_test = self.client.get_channel(int(os.getenv('bot-test-text'))) messages = await channel_bot_test.history(limit=100).flatten() if not messages: return embed = discord.Embed(description='It has been 1 hour, clearing chats...', color=0xff0000) await channel_bot_test.send(embed=embed) await asyncio.sleep(10) await channel_bot_test.purge(limit=None) async def ping(self): # 替换为你要发送pong的频道ID,这里复用bot-test频道为例 channel = self.client.get_channel(int(os.getenv('bot-test-text'))) await channel.send("pong") async def run_schedule(self): # 后台运行aioschedule调度,不阻塞主事件循环 while True: await schedule.run_pending() await asyncio.sleep(0.1) @commands.Cog.listener() async def on_ready(self): # 实例初始化完成后再注册定时任务,传入绑定了self的ping方法 schedule.every(5).seconds.do(self.ping) # 启动调度后台任务 asyncio.create_task(self.run_schedule()) # 启动清理循环任务 self.bot_test_clear.start() print(f'{self.client.user} is now online') def setup(client): client.add_cog(Events(client))
关键改动说明
- 把aioschedule的任务注册移到了
on_ready回调中,此时类实例已经初始化完成,传入self.ping是绑定了当前实例的方法,自动携带self上下文,无需手动传参 - 新增了
run_schedule异步方法作为后台任务运行,替代原来的同步死循环,不会阻塞discord.py的主事件循环 - 修正了
ping方法的发送逻辑,通过频道对象调用发送方法,补充了异步调用的await关键字 - 给
bot_test_clear添加了@tasks.loop(hours=1)装饰器,符合discord.py循环任务的使用规范 - 修正了频道ID获取的类型问题,将环境变量读取的字符串转为整数类型
内容的提问来源于stack exchange,提问作者Broken DEV
相关产品推荐
相关产品推荐

