asyncio, tarea periódica y obtener un valor de retorno
Quiero tener una tarea periódica que cree una lista de tareas pendientes.
Luego ejecuto cada tarea pendiente como una tarea separada.
Cuando la tarea periódica crea una nueva lista de tareas pendientes, quiero detener las tareas pendientes antiguas y ejecutar nuevas tareas pendientes.
Veo dos problemas.
- Solo las funciones
period
parecen ejecutarse (supongo que se debe a la líneagather
).- No puedo devolver un valor desde
do_todo
.
import asyncio
async def repeat(interval, func, *args, **kwargs):
while True:
await asyncio.gather(
func(*args, **kwargs),
asyncio.sleep(interval),
)
async def create_todo():
await asyncio.sleep(1)
print(‘Hola’)
todos = list(range(3))
return todos
async def g():
await asyncio.sleep(0.5)
print(‘Adiós’)
return 2
async def do_todo(x):
await asyncio.sleep(0.5)
print(f’hacer algo con {x}’)
async def main():
create_todo_task = asyncio.create_task(repeat(3, create_todo))
another_task = asyncio.create_task(repeat(2, g))
todos = await create_todo_task
print('tareas pendientes:', todos)
res2 = await another_task
print('resultado de g:', res2)
for todo in todos:
t3 = asyncio.create_task(do_todo(todo))
await t3
asyncio.run(main())
He tomado prestado el código de repeat
de https://stackoverflow.com/a/55505152/433570.
davy.ai
Para abordar el primer problema, solo la función pasada como argumento a
repeat
se ejecutará periódicamente. Dado que se utiliza la funcióngather
, todas las corutinas pasadas a ella se ejecutarán simultáneamente. Por lo tanto, solo las funcionescreate_todo
yg
se ejecutarán periódicamente. Para solucionar esto, puedes crear una tarea separada para cada llamada ado_todo
y ejecutarlas simultáneamente.Para abordar el segundo problema,
do_todo
no devuelve nada, pero puedes usar una cola para comunicarte entre las corutinas. En lugar de devolver un valor desdecreate_todo
, puedes colocar la lista de tareas pendientes en una cola y luego leer desde la cola enmain
.do_todo
también puede colocar sus resultados en otra cola, quemain
puede leer para recopilar los resultados.Aquí tienes un ejemplo de código actualizado:
En este ejemplo,
create_todo
coloca la lista de tareas pendientes enqueue
, quemain
lee.do_todo
coloca su resultado enresults_queue
, quemain
también lee. La funciónrepeat
llama acreate_todo
yg
periódicamente, creando una nueva lista de tareas pendientes y ejecutando cualquier tarea nueva en paralelo con las existentes.