asyncio permite escribir código concurrente basado en un bucle de eventos y corrutinas cooperativas. Ideal para tareas I/O-bound con muchas conexiones simultáneas sin crear miles de hilos.
No ofrece paralelismo de CPU; sirve para solapar esperas de red, disco o timers usando un único hilo.
async def que ceden control con await.asyncio.create_task).Las funciones de asyncio liberan el loop mientras esperan sockets, timers o disco. Usa siempre await en operaciones I/O async (por ejemplo asyncio.sleep, aiohttp).
Si llamas APIs sin await, el trabajo no se ejecuta y perderás errores.
asyncio.gather: ejecuta varias corrutinas en paralelo y espera a todas.return_exceptions=True si quieres recolectar errores sin abortar.asyncio.create_task: programa una corrutina y devuelve una tarea que puedes monitorear o cancelar.Si necesitas llamar a funciones bloqueantes (CPU o librerías sync), usa loop.run_in_executor para no congelar el bucle. Para CPU-bound considera ProcessPoolExecutor; para I/O sync, ThreadPoolExecutor.
Nunca llames directamente a código bloqueante en una corrutina principal: atascarás todo el loop.
await: la corrutina no se ejecuta y el linter suele avisar.Ejemplo sencillo con asyncio y aiohttp (pip install aiohttp) que limita el número de descargas simultáneas.
Incluye manejo básico de timeout y cancelación ordenada.
import asyncio
import aiohttp
URLS = [
"https://www.example.com/",
"https://www.python.org/",
"https://www.infobae.com/"
]
async def fetch(session, url, sem):
async with sem:
async with session.get(url, timeout=5) as resp:
await resp.text()
print(f"Listo: {url} -> {resp.status}")
async def main():
sem = asyncio.Semaphore(5) # límite de concurrencia
async with aiohttp.ClientSession() as session:
tareas = [asyncio.create_task(fetch(session, url, sem)) for url in URLS]
try:
await asyncio.gather(*tareas)
except Exception as exc:
print(f"Alguna tarea fallo: {exc}")
for t in tareas:
t.cancel()
await asyncio.gather(*tareas, return_exceptions=True)
if __name__ == "__main__":
asyncio.run(main())
El semáforo evita lanzar más solicitudes simultáneas de las soportadas. asyncio.run gestiona el event loop y asegura un cierre ordenado de recursos.