How to Periodically Execute a Function With Asyncio

How can I periodically execute a function with asyncio?

For Python versions below 3.5:

import asyncio

@asyncio.coroutine
def periodic():
while True:
print('periodic')
yield from asyncio.sleep(1)

def stop():
task.cancel()

loop = asyncio.get_event_loop()
loop.call_later(5, stop)
task = loop.create_task(periodic())

try:
loop.run_until_complete(task)
except asyncio.CancelledError:
pass

For Python 3.5 and above:

import asyncio

async def periodic():
while True:
print('periodic')
await asyncio.sleep(1)

def stop():
task.cancel()

loop = asyncio.get_event_loop()
loop.call_later(5, stop)
task = loop.create_task(periodic())

try:
loop.run_until_complete(task)
except asyncio.CancelledError:
pass

Scheduling periodic function call in Quart/asyncio

You can use a background task that is started on startup,

async def schedule():
while True:
await asyncio.sleep(1)
await do_work()

@app.before_serving
async def startup():
app.add_background_task(schedule)

which will run schedule for the lifetime of the app, being cancelled at shutdown.

Python 3.9 - Scheduling periodic calls of async function with different parameters

As a ready-to-use solution, you could use aiocron library. If you are not familiar with cron expression syntax, you can use this online editor to check.

Example (this will work on any OS):

import asyncio
from datetime import datetime
import aiocron


async def foo(param):
print(datetime.now().time(), param)


async def main():
cron_min = aiocron.crontab('*/1 * * * *', func=foo, args=("At every minute",), start=True)
cron_hour = aiocron.crontab('0 */1 * * *', func=foo, args=("At minute 0 past every hour.",), start=True)
cron_day = aiocron.crontab('0 9 */1 * *', func=foo, args=("At 09:00 on every day-of-month",), start=True)
cron_week = aiocron.crontab('0 9 * * Mon', func=foo, args=("At 09:00 on every Monday",), start=True)

while True:
await asyncio.sleep(1)

asyncio.run(main())

Output:

15:26:00.003226 At every minute
15:27:00.002642 At every minute
...

asyncio run two different functions periodically with different intervals

Would it be possible using asyncio to run 2 different functions periodically with different interval for each f forever ?

Sure, just create a coroutine that does it in the "obvious" way, by awaiting the coroutine in an infinite loop with asyncio.sleep() between invocations:

import asyncio, time

async def invoke_forever(period, corofn, *args):
while True:
then = time.time()
await corofn(*args)
elapsed = time.time() - then
await asyncio.sleep(period - elapsed)

Scenario described in the question would be set up with something like:

loop = asyncio.get_event_loop()
loop.create_task(invoke_forever(1, f1, 'host1'))
loop.create_task(invoke_forever(2, f2, 'host2'))
loop.run_forever()

You can also use asyncio.gather to combine the two invoke_forever into one awaitable, which allows using the asyncio.run function introduced in Python 3.7:

async def invoke_both():
await asyncio.gather(invoke_forever(1, f1, 'host1'),
invoke_forever(2, f2, 'host2'))

asyncio.run(invoke_both())


Related Topics



Leave a reply



Submit