'Correct way to implement multi timed tasks in python

So I have two pieces of code that control my once a day task

@tasks.loop(hours=24)                
async def daily_task():

Then after I have the code that does the task and whatnot

@daily_task.before_loop
async def before_daily_task():
    now = datetime.now(tz=pytz.timezone('US/Eastern'))
    next_run = now.replace(hour=19, minute=0, second=0)
    if next_run < now:
        next_run += timedelta(days=1)

    await discord.utils.sleep_until(next_run)

This is the code that specifies the specific time, but there is an issue. For having one time it works, but when I add multiple times for multiple guilds it piles them up until they are all complete Server 1: 1:00 Server 2: 1:05 It won't send the message for both guilds until 1:05 because of the before_loop. What would be the best work around for this?



Solution 1:[1]

async def daily_task():  # function that will loop, note: no decorator
    ...


def before_daily_task(hour=0, minute=0, second=0):  # not asynchronous!
    async def wrapper():  # asynchronous!
        # here the code that's in your `before_daily_task`
        # use `hour`, `minute` and `second` to calculate how much to sleep
    return wrapper  # not calling


def task_generator(hour=0, minute=0, second=0):  # I guess you can take a guild ID or a channel ID too
    task = tasks.loop(hours=24)(daily_task)
    task.before_loop(before_daily_task(19, 5, 00))
    task.start()  # pass the guild/channel ID here
    return task


# start the task at a specified time
task_generator(24, 0, 0)

Since you can only start each task once, I created a task generator to create a task on the fly, using the hour provided.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Łukasz Kwieciński