Python async-await no está esperando.
No he trabajado mucho con Python asíncrono, pero actualmente tengo un proyecto con el marco de trabajo Sanic. Hay un punto final de websocket que recibe datos del cliente, envía un mensaje al cliente indicando que se ha iniciado la tarea, luego ejecuta una tarea larga de sincronización (no hay opciones para hacerlo asíncrono) y finalmente envía un mensaje al cliente indicando que la tarea está terminada. Aquí hay un código de ejemplo:
from sanic import Sanic
from sanic.server.protocols.websocket_protocol import WebSocketProtocol
app = Sanic("TestApp")
@app.websocket("/")
async def procesar_tarea(request, ws: WebSocketServerProtocol):
datos_crudos = await ws.recv()
datos = json.loads(datos_crudos)
await ws.send("TAREA INICIADA")
procesar_tarea_larga(datos) # Función de sincronización larga
await ws.send("TAREA FINALIZADA")
Pero hay un problema. La función no espera a ws.send("TAREA INICIADA")
. De hecho, ambos mensajes se envían solo después de que procesar_tarea_larga
termina. Sin embargo, funciona correctamente si agrego await asyncio.sleep(0.1)
después de await ws.send("TAREA INICIADA")
.
¿Alguien puede señalarme qué está mal en mi código?
davy.ai
El problema con el código es que no permite que el bucle de eventos ejecute el método send() antes de ejecutar la función process_long_task(). Aunque el método send() es asíncrono, no se está esperando su finalización antes de ejecutar la tarea de sincronización larga. Para solucionar esto, puedes utilizar asyncio.create_task() para ejecutar la tarea de sincronización larga en segundo plano mientras permite que el bucle de eventos continúe ejecutando otras tareas, incluyendo el envío del mensaje al cliente.
Aquí tienes un ejemplo actualizado:
En este código actualizado, el método send() se espera antes de llamar a create_task() para ejecutar la tarea de sincronización larga en segundo plano. Además, se utiliza asyncio.sleep(0) para permitir que el bucle de eventos ejecute el método send() antes de ejecutar la tarea. La tarea de sincronización larga se ejecuta utilizando create_task() para que se ejecute en segundo plano y no bloquee el bucle de eventos. Finalmente, se envía el segundo mensaje después de que la tarea esté completa.