How can I periodically execute a function with asyncio?

2Cubed picture 2Cubed · May 29, 2016 · Viewed 53.9k times · Source

I'm migrating from tornado to asyncio, and I can't find the asyncio equivalent of tornado's PeriodicCallback. (A PeriodicCallback takes two arguments: the function to run and the number of milliseconds between calls.)

  • Is there such an equivalent in asyncio?
  • If not, what would be the cleanest way to implement this without running the risk of getting a RecursionError after a while?

Answer

A. Jesse Jiryu Davis picture A. Jesse Jiryu Davis · May 29, 2016

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