Asincronía con asyncio: concurrencia eficiente para I/O en Python

Comprende `async/await`, event loop y tareas concurrentes para mejorar throughput en operaciones de red o disco sin bloquear.

La asincronía en Python está orientada principalmente a cargas I/O-bound: red, APIs, colas, archivos, sockets.

`async def` define coroutines y `await` cede control al event loop mientras se espera una operación no bloqueante.

No confundir concurrencia asíncrona con paralelismo CPU: para CPU intensivo, asyncio no suele ser la herramienta principal.

Usar `asyncio.gather` permite ejecutar múltiples tareas I/O en paralelo lógico con menor tiempo total de espera.

  • El event loop coordina tareas cooperativas; cada `await` abre espacio para otras tareas.
  • Una coroutine no se ejecuta por sí sola: debe ser esperada (`await`) o programada como tarea.
  • `asyncio.run(...)` crea y gestiona el loop principal para scripts simples.
  • Si una coroutine llama funciones bloqueantes (por ejemplo `time.sleep`), se rompe la ventaja asíncrona.
  • La ganancia aparece cuando esperas múltiples operaciones I/O independientes.

1) Modelo mental: coroutine + event loop

El event loop coordina tareas cooperativas; cada `await` abre espacio para otras tareas.

Una coroutine no se ejecuta por sí sola: debe ser esperada (`await`) o programada como tarea.

`asyncio.run(...)` crea y gestiona el loop principal para scripts simples.

Si una coroutine llama funciones bloqueantes (por ejemplo `time.sleep`), se rompe la ventaja asíncrona.

2) Ejecutar tareas concurrentes con gather

La ganancia aparece cuando esperas múltiples operaciones I/O independientes.

Con ejecución secuencial, tres llamadas de 1s tardan ~3s. Con `gather`, pueden completar cerca de ~1s total.

`gather` devuelve resultados en el orden de las tareas enviadas.

Maneja excepciones conscientemente (`return_exceptions=True`) si no quieres abortar todo el lote al primer fallo.

3) Errores comunes y buenas prácticas

La asincronía mal aplicada complica más de lo que ayuda.

Si necesitas librerías síncronas en flujo async, evalúa wrappers específicos o ejecución en hilos/procesos según caso.

Medir latencia y throughput antes/después te ayuda a justificar complejidad añadida.

Asincronía es una herramienta de arquitectura, no un fin en sí mismo.

  • No mezcles funciones bloqueantes dentro de coroutines críticas.
  • Define límites de concurrencia (semaforos) si llamas APIs con rate limit.
  • Cancela tareas huérfanas y controla timeout por operación.
  • Mantén separación entre capa asíncrona y dominio de negocio.
Python
21

Asincronía con asyncio: concurrencia eficiente para I/O en Python

Comprende `async/await`, event loop y tareas concurrentes para mejorar throughput en operaciones de red o disco sin bloquear.

Código del tema: async def main(): await tarea()

📘 Teoría

1) Modelo mental: coroutine + event loop

El event loop coordina tareas cooperativas; cada `await` abre espacio para otras tareas.

1

Una coroutine no se ejecuta por sí sola: debe ser esperada (`await`) o programada como tarea.

2

`asyncio.run(...)` crea y gestiona el loop principal para scripts simples.

3

Si una coroutine llama funciones bloqueantes (por ejemplo `time.sleep`), se rompe la ventaja asíncrona.

Coroutine mínima
import asyncio


async def saludo() -> None:
    await asyncio.sleep(0.2)
    print('hola async')


asyncio.run(saludo())

2) Ejecutar tareas concurrentes con gather

La ganancia aparece cuando esperas múltiples operaciones I/O independientes.

1

Con ejecución secuencial, tres llamadas de 1s tardan ~3s. Con `gather`, pueden completar cerca de ~1s total.

2

`gather` devuelve resultados en el orden de las tareas enviadas.

3

Maneja excepciones conscientemente (`return_exceptions=True`) si no quieres abortar todo el lote al primer fallo.

Concurrencia de tareas I/O
import asyncio


async def pedir(id_: int) -> str:
    await asyncio.sleep(1)
    return f'dato-{id_}'


async def main() -> None:
    resultados = await asyncio.gather(pedir(1), pedir(2), pedir(3))
    print(resultados)


asyncio.run(main())

3) Errores comunes y buenas prácticas

La asincronía mal aplicada complica más de lo que ayuda.

Si necesitas librerías síncronas en flujo async, evalúa wrappers específicos o ejecución en hilos/procesos según caso.

Medir latencia y throughput antes/después te ayuda a justificar complejidad añadida.

Asincronía es una herramienta de arquitectura, no un fin en sí mismo.

  • No mezcles funciones bloqueantes dentro de coroutines críticas.
  • Define límites de concurrencia (semaforos) si llamas APIs con rate limit.
  • Cancela tareas huérfanas y controla timeout por operación.
  • Mantén separación entre capa asíncrona y dominio de negocio.
Timeout defensivo
import asyncio


async def tarea_lenta() -> str:
    await asyncio.sleep(2)
    return 'ok'


async def main() -> None:
    try:
        res = await asyncio.wait_for(tarea_lenta(), timeout=1)
        print(res)
    except TimeoutError:
        print('timeout controlado')


asyncio.run(main())

🧪 Aprende probando

Ejemplo Ejemplo: procesar lote de llamadas concurrentes Simula peticiones I/O concurrentes y muestra diferencia conceptual frente a secuencial.

🏁 Retos

Reto Reto: añade espera asíncrona Completa la coroutine para ceder control al event loop.

🧰 Recursos

Test

Comprueba tus conocimientos con un test sobre Python.

Test de Python

¿Qué es esto?

Soy Cristian Eslava y a veces hago webs para procrastinar yo y vosotros 😉.

Esta la hice en febrero de 2026 para facilitar el aprendizaje de mis alumnxs. Aprender desarrollo web practicando. La idea es que crezca semanalmente con nuevos temas, tests y retos.

Inspirado en MDN, en W3Schools, en Codepen, en el crack de Manz y en mil sitios de documentación sobre desarrollo web. Quería aportar además de bloques teóricos con ejemplos, la gamificación de los retos y el sistema de test que ya tenía en culTest .

Si te gustó, si no te gustó, si quieres saludarme, o invitarme a 🍻 no dudes en escribirme en cristianeslava@gmail.com .