如何在 discord.py 中创建多个循环后台任务(不重写)

How to create multiple looping background tasks in discord.py (Not rewrite)

我一直在尝试为我的 discord.py 机器人添加一个循环后台任务系统,但是一旦一个任务开始 运行ning,它将阻止其他任务。我试过到处寻找答案,但要么他们使用 discord.py 的重写版本,要么他们只有一项任务。

我正在尝试并行执行任务 运行,因此所有任务都可以同时 运行。

这是我的代码:

# hiding imports

class BackgroundTasksCollection:
    def __init__(self, client: discord.Client):
        self.client = client

    async def start_tasks(self):
        tasks = []
        for name in dir(self):
            if name.startswith("task_"):
                print(name)
                tasks.append(getattr(self, name))

        [await self.client.loop.create_task(task()) for task in tasks]

    # tasks
    async def task_1(self):  # only this will run because the tasks are started in alphabetical order
        await self.client.wait_until_ready()
        while not self.client.is_closed():
            await asyncio.sleep(60 * 60)

            # ...

    async def task_2(self):
        await self.client.wait_until_ready()
        while not self.client.is_closed():
            await asyncio.sleep(1)

            # ...

    async def task_3(self):
        await self.client.wait_until_ready()
        while not self.client.is_closed():
            await asyncio.sleep(30)

            # ...
class MyClient(discord.Client):
    def __init__(self, **options):
        super().__init__(**options)
        self.tasks = BackgroundTasksCollection(self)

    async def on_ready(self):
        # ...
        await self.tasks.start_tasks()
    
    # handle message, errors, etc.

您可能应该查看 documentation

中的任务

这来自上面链接的文档:

from discord.ext import tasks, commands

class MyCog(commands.Cog):
    def __init__(self, bot):
        self.index = 0
        self.bot = bot
        self.printer.start()

    def cog_unload(self):
        self.printer.cancel()

    @tasks.loop(seconds=5.0)
    async def printer(self):
        print(self.index)
        self.index += 1

    @printer.before_loop
    async def before_printer(self):
        print('waiting...')
        await self.bot.wait_until_ready()