Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to schedule a task in asyncio so it runs at a certain date?

My program is supposed to run 24/7 and i want to be able to run some tasks at a certain hour/date.

I have already tried to work with aiocron but it only supports scheduling functions (not coroutines) and i have read that is not a really good library. My program is built so most if not all the tasks that i would want to schedule are built in coroutines.

Is there any other library that allows for such kind of task scheduling?

Or if not, any way of warping coroutines so they run of a normal function?

like image 630
Laikar Avatar asked Jul 11 '18 18:07

Laikar


People also ask

How many times should Asyncio run () be called?

It should be used as a main entry point for asyncio programs, and should ideally only be called once. New in version 3.7.

What does await do in Asyncio?

The keyword await passes function control back to the event loop. (It suspends the execution of the surrounding coroutine.) If Python encounters an await f() expression in the scope of g() , this is how await tells the event loop, “Suspend execution of g() until whatever I'm waiting on—the result of f() —is returned.

What is event loop in Asyncio?

The event loop is the core of every asyncio application. Event loops run asynchronous tasks and callbacks, perform network IO operations, and run subprocesses. Application developers should typically use the high-level asyncio functions, such as asyncio.


Video Answer


1 Answers

I have already tried to work with aiocron but it only supports scheduling functions (not coroutines)

According to the examples at the link you provided, that does not appear to be the case. The functions decorated with @asyncio.coroutine are equivalent to coroutines defined with async def, and you can use them interchangeably.

However, if you want to avoid aiocron, it is straightforward to use asyncio.sleep to postpone running a coroutine until an arbitrary point in time. For example:

import asyncio, datetime

async def wait_until(dt):
    # sleep until the specified datetime
    now = datetime.datetime.now()
    await asyncio.sleep((dt - now).total_seconds())

async def run_at(dt, coro):
    await wait_until(dt)
    return await coro

Example usage:

async def hello():
    print('hello')

loop = asyncio.get_event_loop()
# print hello ten years after this answer was written
loop.create_task(run_at(datetime.datetime(2028, 7, 11, 23, 36),
                        hello()))
loop.run_forever()

Note: Python versions before 3.8 didn't support sleeping intervals longer than 24 days, so wait_until had to work around the limitation. The original version of this answer defined it like this:

async def wait_until(dt):
    # sleep until the specified datetime
    while True:
        now = datetime.datetime.now()
        remaining = (dt - now).total_seconds()
        if remaining < 86400:
            break
        # pre-3.7.1 asyncio doesn't like long sleeps, so don't sleep
        # for more than one day at a time
        await asyncio.sleep(86400)
    await asyncio.sleep(remaining)

The limitation was removed in Python 3.8 and the fix was backported to 3.6.7 and 3.7.1.

like image 155
user4815162342 Avatar answered Oct 12 '22 11:10

user4815162342