Python Asyncio: Programación asíncrona moderna

Domina asyncio para escribir código Python concurrente y eficiente

CodeCraft Master
17 de febrero de 2026
15 min
745 views

Python Asyncio: Programación asíncrona moderna

Asyncio es la biblioteca de Python para escribir código concurrente usando la sintaxis async/await, permitiéndote manejar miles de operaciones I/O simultáneamente.

Lo básico: async y await

import asyncio

async def saludar(nombre):
    print(f"Hola {nombre}")
    await asyncio.sleep(1)
    print(f"Adiós {nombre}")

# Ejecutar la corrutina
asyncio.run(saludar("Roberto"))

Ejecutar múltiples tareas

async def tarea(n):
    print(f"Tarea {n} iniciada")
    await asyncio.sleep(n)
    print(f"Tarea {n} completada")
    return f"Resultado {n}"

async def main():
    # Ejecutar tareas concurrentemente
    resultados = await asyncio.gather(
        tarea(1),
        tarea(2),
        tarea(3)
    )
    print(resultados)

asyncio.run(main())

Ejemplo práctico: Web Scraper

import asyncio
import aiohttp
from time import time

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
        'https://example.com',
        'https://python.org',
        'https://github.com'
    ]
    
    inicio = time()
    
    async with aiohttp.ClientSession() as session:
        tareas = [fetch_url(session, url) for url in urls]
        resultados = await asyncio.gather(*tareas)
    
    print(f"Tiempo total: {time() - inicio:.2f} segundos")
    print(f"Páginas descargadas: {len(resultados)}")

asyncio.run(main())

Timeout y cancelación

async def operacion_larga():
    await asyncio.sleep(10)
    return "Completado"

async def main():
    try:
        # Timeout de 3 segundos
        resultado = await asyncio.wait_for(
            operacion_larga(),
            timeout=3.0
        )
    except asyncio.TimeoutError:
        print("La operación tomó demasiado tiempo")

asyncio.run(main())

Tareas en background

async def monitor():
    while True:
        print("Monitoreando...")
        await asyncio.sleep(5)

async def main():
    # Crear tarea en background
    tarea_monitor = asyncio.create_task(monitor())
    
    # Hacer otras cosas
    await asyncio.sleep(20)
    
    # Cancelar la tarea
    tarea_monitor.cancel()
    try:
        await tarea_monitor
    except asyncio.CancelledError:
        print("Monitor detenido")

asyncio.run(main())

Async Context Managers

class AsyncDatabaseConnection:
    async def __aenter__(self):
        print("Conectando a la base de datos...")
        await asyncio.sleep(1)
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        print("Cerrando conexión...")
        await asyncio.sleep(1)
    
    async def query(self, sql):
        print(f"Ejecutando: {sql}")
        await asyncio.sleep(0.5)
        return [{"id": 1, "name": "Roberto"}]

async def main():
    async with AsyncDatabaseConnection() as db:
        resultado = await db.query("SELECT * FROM users")
        print(resultado)

asyncio.run(main())

Async Generators

async def fetch_pages(urls):
    for url in urls:
        await asyncio.sleep(1)  # Simular request
        yield f"Contenido de {url}"

async def main():
    urls = ['url1', 'url2', 'url3']
    
    async for contenido in fetch_pages(urls):
        print(contenido)

asyncio.run(main())

Semáforos para limitar concurrencia

async def hacer_request(semaforo, url):
    async with semaforo:
        print(f"Procesando {url}")
        await asyncio.sleep(2)
        return f"Resultado de {url}"

async def main():
    # Máximo 3 requests simultáneos
    semaforo = asyncio.Semaphore(3)
    
    urls = [f"url{i}" for i in range(10)]
    tareas = [hacer_request(semaforo, url) for url in urls]
    
    resultados = await asyncio.gather(*tareas)
    print(resultados)

asyncio.run(main())

Sincronización: Locks y Events

lock = asyncio.Lock()
contador = 0

async def incrementar():
    global contador
    async with lock:
        temp = contador
        await asyncio.sleep(0.1)
        contador = temp + 1

async def main():
    await asyncio.gather(*[incrementar() for _ in range(10)])
    print(f"Contador final: {contador}")

asyncio.run(main())

Comparación: Sync vs Async

# Síncrono - 6 segundos total
def sync_version():
    time.sleep(2)
    time.sleep(2)
    time.sleep(2)

# Asíncrono - 2 segundos total
async def async_version():
    await asyncio.gather(
        asyncio.sleep(2),
        asyncio.sleep(2),
        asyncio.sleep(2)
    )

Conclusión

Asyncio es ideal para operaciones I/O bound (requests HTTP, lectura de archivos, queries a DB). Para operaciones CPU bound, considera usar multiprocessing en su lugar.

C

CodeCraft Master

Desarrollador Full Stack apasionado por compartir conocimiento. Escribo sobre JavaScript, TypeScript, React y desarrollo web moderno.

Artículos Relacionados

Únete a nuestro boletín

Recibe contenido exclusivo de desarrollo web directamente en tu bandeja de entrada.

  • Contenido exclusivo de desarrollo web

  • Actualizaciones semanales

  • Tips y trucos

  • Sin spam, solo contenido de calidad

Al suscribirte, aceptas recibir correos electrónicos. Puedes cancelar tu suscripción en cualquier momento.