Programar llamadas a funciones regulares

Además de gestionar las co-rutinas y devoluciones de llamadas de E/S, el bucle de eventos asyncio puede programar llamadas a funciones regulares basadas en el valor del temporizador mantenido en el bucle.

Programar una devolución de llamada «Pronto»

Si el tiempo de la devolución de llamada no importa, call_soon() puede ser utilizado para programar la llamada para la siguiente iteración del bucle. Cualquier argumento posicional adicional después de la función se pasan a la devolución de llamada cuando se invoca. Para pasar argumentos clave a la devolución de llamada, usa partial() del módulo functools.

asyncio_call_soon.py
import asyncio
import functools


def callback(arg, *, kwarg='default'):
    print('callback invoked with {} and {}'.format(arg, kwarg))


async def main(loop):
    print('registering callbacks')
    loop.call_soon(callback, 1)
    wrapped = functools.partial(callback, kwarg='not default')
    loop.call_soon(wrapped, 2)

    await asyncio.sleep(0.1)


event_loop = asyncio.get_event_loop()
try:
    print('entering event loop')
    event_loop.run_until_complete(main(event_loop))
finally:
    print('closing event loop')
    event_loop.close()

Las devoluciones de llamada se invocan en el orden en que son programadas.

$ python3 asyncio_call_soon.py

entering event loop
registering callbacks
callback invoked with 1 and default
callback invoked with 2 and not default
closing event loop

Programar de una devolución de llamada con un retraso

Para posponer una devolución de llamada hasta algún momento en el futuro, usa call_later(). El primer argumento es el retraso en segundos y el segundo argumento es la función de devolución de llamada.

asyncio_call_later.py
import asyncio


def callback(n):
    print('callback {} invoked'.format(n))


async def main(loop):
    print('registering callbacks')
    loop.call_later(0.2, callback, 1)
    loop.call_later(0.1, callback, 2)
    loop.call_soon(callback, 3)

    await asyncio.sleep(0.4)


event_loop = asyncio.get_event_loop()
try:
    print('entering event loop')
    event_loop.run_until_complete(main(event_loop))
finally:
    print('closing event loop')
    event_loop.close()

En este ejemplo, la misma función de devolución de llamada está programada para diferentes tiempos con diferentes argumentos. La instancia final, utiliza call_soon(), hace que se invoque la devolución de llamada con el argumento 3 antes de cualquiera de las instancias programadas, mostrando que «pronto» suele implicar un retraso mínimo.

$ python3 asyncio_call_later.py

entering event loop
registering callbacks
callback 3 invoked
callback 2 invoked
callback 1 invoked
closing event loop

Programar de una devolución de llamada para un momento específico

También es posible programar una llamada para que se realice en un momento determinado. El bucle utiliza un reloj monotónico, en lugar de un reloj de pared, para garantizar que el valor de «ahora» nunca retroceda. Para elegir un momento para una devolución de llamada programada es necesario comenzar desde el estado interno de ese reloj usando el método time() del bucle.

asyncio_call_at.py
import asyncio
import time


def callback(n, loop):
    print('callback {} invoked at {}'.format(n, loop.time()))


async def main(loop):
    now = loop.time()
    print('clock time: {}'.format(time.time()))
    print('loop  time: {}'.format(now))

    print('registering callbacks')
    loop.call_at(now + 0.2, callback, 1, loop)
    loop.call_at(now + 0.1, callback, 2, loop)
    loop.call_soon(callback, 3, loop)

    await asyncio.sleep(1)


event_loop = asyncio.get_event_loop()
try:
    print('entering event loop')
    event_loop.run_until_complete(main(event_loop))
finally:
    print('closing event loop')
    event_loop.close()

Ten en cuenta que el tiempo de acuerdo con el bucle no coincide con el valor devuelto por time.time().

$ python3 asyncio_call_at.py

entering event loop
clock time: 1521404411.833459
loop  time: 715855.398664185
registering callbacks
callback 3 invoked at 715855.398744743
callback 2 invoked at 715855.503897727
callback 1 invoked at 715855.601119414
closing event loop