Event loop de asyncio: creación manual y debugging avanzado
Clase 14 de 17 • Curso de Python Profesional: Arquitectura de Proyectos, Entornos y PyPI
Domina el event loop de asyncio con ejemplos claros y prácticos. Aquí verás cómo funciona, cuándo conviene usar asyncio.run y cuándo gestionar el loop manualmente, además de activar debug para entender qué sucede bajo el capó sin bloquear tu programa.
¿Qué es el event loop en asyncio y cómo coordina corutinas?
El event loop es el corazón de asyncio: coordina corutinas y decide cuándo pausarlas y reanudarlas. Piensa en un director de orquesta que no ejecuta, pero hace que todo suene a tiempo.
- Revisa tareas listas. Busca corutinas listas para ejecutarse.
- Ejecuta hasta la await. Corre cada tarea hasta encontrar un await.
- Pausa y registra. Guarda el estado y anota qué está esperando.
- Repite el ciclo. Permite progreso continuo de múltiples operaciones de IO sin bloquear.
¿Qué pasos clave siguen las tareas en el loop?
- Se seleccionan tareas pendientes y se programan de forma no bloqueante.
- Cada tarea avanza hasta su siguiente punto de espera con await.
- El loop retoma tareas cuando su condición de espera se cumple.
¿Cuándo usar asyncio.run y cuándo gestión manual del loop?
En la mayoría de casos, usa asyncio.run: es más simple y seguro. Evita sobrecarga y maneja automáticamente la creación y cierre del loop.
Usa gestión manual del loop cuando:
- Necesitas control fino del ciclo de vida del loop.
- Integras asyncio con otros frameworks que ya manejan bucles de eventos.
- Requieres debugging avanzado: activar debug y observar el comportamiento interno de asyncio.
¿Cómo crear y depurar un event loop manual en Python?
Puedes crear tu propio loop para tener acceso directo a su configuración. El flujo es: crear el loop, registrarlo en asyncio, ejecutar hasta completar la tarea y cerrarlo al final para liberar recursos.
import asyncio
async def main():
# tu lógica asíncrona aquí
return "ok"
# crear y registrar el loop
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
# opcional: activar debug del loop
loop.set_debug(True)
# ejecutar hasta que la tarea termine
loop.run_until_complete(main())
finally:
# importante: cerrar el loop para liberar recursos
loop.close()
- new_event_loop. Crea una instancia de loop y la guarda en una variable, por ejemplo, my_loop.
- set_event_loop. Indica a asyncio cuál loop debe usar.
- run_until_complete. Ejecuta la tarea hasta completarse.
- close. Cierra el loop en un bloque finally para no dejar recursos abiertos.
¿Cómo activar debug y ver logs de asyncio?
- Usa loop.set_debug(True) para habilitar debug en el loop.
- Ajusta tu configuración de logs a nivel debug para ver mensajes de asyncio, como el “selector” que está usando.
- Ejecuta tu script y observa el logging de asyncio para entender qué tareas se seleccionan y cuándo avanzan.
Consejos prácticos:
- En proyectos comunes, asyncio.run es suficiente y recomendable.
- El control manual del loop es útil para escenarios específicos de integración y debug profundo.
- Mantén la limpieza de recursos: siempre cierra el loop.
¿Te animas a practicar? Integra una librería para consultas a APIs de manera asíncrona y pruébala con gestión manual del loop o con asyncio.run. Comparte dudas y avances en comentarios.