Saltar al contenido principal
Python intermedio2026-07-29 · 11 min de lectura

Python async / await Explicado: el tutorial de 2026

Async en Python tiene fama de ser confuso. No tiene por qué ser así. Una vez que internaliza una oración (async permite que UN subproceso ejecute múltiples tareas vinculadas a E/S intercaladas), todo lo demás sigue.

Este tutorial cubre: qué hacen realmente async def y await, cuándo gana async y cuándo es la herramienta incorrecta, los cuatro patrones que utiliza cada código base asíncrono (secuencial, recopilación, semáforo, tiempo de espera) y las tres formas en que los principiantes se tragan los errores en silencio.

El modelo mental de una frase

Async en Python es concurrencia cooperativa en un solo hilo. Cuando su código llega a "esperar", el control regresa al bucle de eventos, que puede ejecutar otra tarea mientras la primera espera E/S. Cuando se completa la E/S, el bucle reanuda la primera tarea desde donde se detuvo.

Eso es todo. Sin subprocesos, sin procesos, sin paralelismo (en el sentido de CPython-con-GIL). Solo un hilo que hace malabarismos con muchas tareas que pasan la mayor parte del tiempo esperando en la red/disco/base de datos.

Async es más rápido cuando el cuello de botella está esperando, no computando.

El programa asíncrono mínimo viable de tres líneas

▶ PYTHONeditable · runs in your browser
  • async def hello() — declara una corrutina. Llamar a hello() no ejecuta el código; crea un objeto de rutina.
  • await asyncio.sleep(1): devuelve el control al bucle de eventos durante 1 segundo.
  • asyncio.run(hello()): crea un bucle de eventos y ejecuta la rutina hasta su finalización.

Regla: `await` solo dentro de `async def`. Llamar a "await" en una función normal es un "SyntaxError".

Cuando async gana (y cuando no)

Async gana: trabajo vinculado a E/S

Cualquier tarea que pase la mayor parte del tiempo ESPERANDO es candidata a asincrónica:

  • Solicitudes HTTP (API externas, scraping, webhooks)
  • Consultas de bases de datos.
  • Lectura/escritura de archivos
  • Secuencias WebSocket/gRPC
  • Consumidores de cola (Redis, RabbitMQ, Kafka)

Ejemplo: obtener 100 URL.

▶ PYTHONeditable · runs in your browser

Aceleración del reloj de pared de 50 a 100 veces para trabajos con muchas E/S. Aquí es donde async gana su presupuesto de complejidad.

Async LOSES: trabajo vinculado a la CPU

Async no ofrece ningún paralelismo para el cálculo. Dado que es cooperativo de un solo subproceso, un bucle de CPU bloquea todo el bucle de eventos.

▶ PYTHONeditable · runs in your browser

Todas las demás tareas mueren de hambre mientras se ejecuta "pbkdf2". Para trabajos vinculados a la CPU, busque multiprocesamiento o concurrent.futures.ProcessPoolExecutor, no asíncrono.

Carga de trabajo mixta: run_in_executor

Si UN paso requiere mucha CPU y el resto es E/S, ajuste el paso de la CPU para que se ejecute en un grupo de subprocesos sin bloquear el bucle:

▶ PYTHONeditable · runs in your browser

Ninguno = grupo de subprocesos predeterminado. Excelente para llamar a bibliotecas de sincronización de terceros que son lentas pero que no se pueden reescribir.

Los cuatro patrones

1. Secuencial: una tarea a la vez

▶ PYTHONeditable · runs in your browser

Úselo cuando cada solicitud dependa del resultado de la anterior.

2. asyncio.gather: dispara todo a la vez

▶ PYTHONeditable · runs in your browser

Elección predeterminada para tareas de E/S independientes. Pero: si reúne 10,000 tareas en una API, obtendrá descriptores de archivos agotados o con velocidad limitada. Ahí es donde entra en juego el patrón de semáforo.

3. Semáforo: límite de concurrencia

▶ PYTHONeditable · runs in your browser

asyncio.Semaphore(N) permite como máximo N tareas pasar el async with sem: en cualquier momento. Las otras tareas se ponen en cola. Úselo para cualquier API externa con un límite de velocidad o una base de datos con un grupo de conexiones.

4. Tiempo de espera: abandonar el trabajo lento

▶ PYTHONeditable · runs in your browser

asyncio.wait_for cancela la tarea subyacente después de N segundos. Esencial para cualquier código asíncrono que se comunique con una red; nunca haga una espera ilimitada.

Las tres trampas para tragar errores

Trampa 1: asyncio.gather con return_exceptions=True

▶ PYTHONeditable · runs in your browser

Útil cuando desea conservar resultados parciales pero LETAL si no verifica todos los resultados:

▶ PYTHONeditable · runs in your browser

Sin la verificación, los errores desaparecen silenciosamente.

Trampa 2: Tareas de disparar y olvidar

▶ PYTHONeditable · runs in your browser

Si se activa background_work(), Python emite una advertencia al apagar y continúa. Para cualquier cosa que le interese, almacene la tarea y "espérela" o use "asyncio.TaskGroup" (3.11+) que propaga todos los errores.

Trampa 3: código de sincronización dentro de async

▶ PYTHONeditable · runs in your browser

Las "solicitudes" son sincrónicas. Incluso dentro de un async def, requests.get bloquea todo el ciclo hasta que llega la respuesta. Utilice httpx (o aiohttp) para HTTP asíncrono.

Regla: nunca use una biblioteca de E/S síncrona dentro de código asíncrono. Si la biblioteca no tiene una variante asíncrona, envuélvala en run_in_executor.

asyncio.TaskGroup: la forma de desplegarse en 2026

Python 3.11 agregó TaskGroup, que soluciona limpiamente el problema de disparar y olvidar:

▶ PYTHONeditable · runs in your browser

Simultaneidad estructurada: sin errores perdidos ni tareas huérfanas. Prefiere esto a create_task en el código moderno.

Ejemplo del mundo real: raspador de tasa limitada

▶ PYTHONeditable · runs in your browser

Los cuatro patrones en 15 líneas: concurrencia limitada (semáforo), tiempos de espera (wait_for), ramas de error explícito (sin deglución) y recopilación para distribución en abanico. Copie y pegue esta forma en cualquier tarea de E/S asíncrona.


Async en Python tiene una curva de aprendizaje real, pero el modelo mental es simple: un hilo, la cooperación se detiene en "espera", las E/S se superponen. Domine gather + Semaphore + wait_for + TaskGroup y habrá cubierto el 95% del trabajo asíncrono que jamás escribirá.

Siguiente paso: la pista de Python para estudiantes de último año tiene 20 lecciones prácticas sobre asyncio, TaskGroup, aiohttp/httpx y los patrones de concurrencia anteriores, con Python real ejecutándose en su navegador.

¿Listo para probarlo?

15 lecciones gratis después de un registro gratuito, sin tarjeta. Pruebe la plataforma y luego decida.

Empieza gratis →

Or unlock every lesson

Pro — $12/mo, unlimited AI, cancel any time. Refund within 14 days worldwide.

See Pro plans →

Get one Python lesson + one career idea every Friday

No spam, no "buy our course now". Three bullets, every Friday. Unsubscribe with one click.