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
.
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.
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.
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