Producir resultados de forma asíncrona¶
Un Futuro
representa el resultado de un trabajo que no ha sido completado
aún. El bucle de eventos puede seguir el estado de un objeto Future
para
indicar que está listo, permitiendo que una parte de una aplicación espere otra
parte para terminar un trabajo.
Esperando un futuro¶
Un Future
actúa como una co-rutina, por lo que cualquier técnica útil para
esperar a una co-rutina también puede usarse para esperar que el futuro sea
marcado como listo. Este ejemplo pasa el futuro al método
run_until_complete()
del bucle de eventos.
import asyncio
def mark_done(future, result):
print('setting future result to {!r}'.format(result))
future.set_result(result)
event_loop = asyncio.get_event_loop()
try:
all_done = asyncio.Future()
print('scheduling mark_done')
event_loop.call_soon(mark_done, all_done, 'the result')
print('entering event loop')
result = event_loop.run_until_complete(all_done)
print('returned result: {!r}'.format(result))
finally:
print('closing event loop')
event_loop.close()
print('future result: {!r}'.format(all_done.result()))
El estado del Future
cambia a listo cuando se llama set_result()
, y la
instancia Future
mantiene el resultado dado al método de recuperación
posterior.
$ python3 asyncio_future_event_loop.py
scheduling mark_done
entering event loop
setting future result to 'the result'
returned result: 'the result'
closing event loop
future result: 'the result'
Un Future
también se puede usar con la palabra clave await
, como en
este ejemplo.
import asyncio
def mark_done(future, result):
print('setting future result to {!r}'.format(result))
future.set_result(result)
async def main(loop):
all_done = asyncio.Future()
print('scheduling mark_done')
loop.call_soon(mark_done, all_done, 'the result')
result = await all_done
print('returned result: {!r}'.format(result))
event_loop = asyncio.get_event_loop()
try:
event_loop.run_until_complete(main(event_loop))
finally:
event_loop.close()
El resultado de Future
es devuelto por await
, por lo que es con
frecuencia es posible tener el mismo código de trabajo con una co-rutina normal
y una instancia Future
.
$ python3 asyncio_future_await.py
scheduling mark_done
setting future result to 'the result'
returned result: 'the result'
Devoluciones de llamadas de Futures¶
Además de trabajar como una co-rutina, un Future
puede invocar devoluciones
de llamada cuando se completa. Las devoluciones de llamada se invocan en el
orden en que están registrados
import asyncio
import functools
def callback(future, n):
print('{}: future done: {}'.format(n, future.result()))
async def register_callbacks(all_done):
print('registering callbacks on future')
all_done.add_done_callback(functools.partial(callback, n=1))
all_done.add_done_callback(functools.partial(callback, n=2))
async def main(all_done):
await register_callbacks(all_done)
print('setting result of future')
all_done.set_result('the result')
event_loop = asyncio.get_event_loop()
try:
all_done = asyncio.Future()
event_loop.run_until_complete(main(all_done))
finally:
event_loop.close()
La devolución de llamada debe esperar un argumento, la instancia Future
.
Para pasar argumentos adicionales a las devoluciones de llamada, use
functools.partial()
para crear un envoltorio.
$ python3 asyncio_future_callback.py
registering callbacks on future
setting result of future
1: future done: the result
2: future done: the result