FastAPI: Asincronía
Descubre cómo usar la programación asíncrona en FastAPI para mejorar el rendimiento y gestionar múltiples tareas concurrentes en aplicaciones web.
Aprende FastAPI GRATIS y certifícateAsincronía en FastAPI
La programación asíncrona representa un paradigma fundamental en el desarrollo web moderno, especialmente relevante cuando trabajamos con FastAPI. A diferencia de la programación tradicional síncrona, donde cada operación debe completarse antes de continuar con la siguiente, la asincronía permite que nuestras aplicaciones manejen múltiples tareas de forma concurrente.
¿Qué es la programación asíncrona?
En el contexto de aplicaciones web, la asincronía resulta especialmente valiosa cuando realizamos operaciones que requieren tiempo de espera, como consultas a bases de datos, llamadas a APIs externas o lectura de archivos. En lugar de bloquear toda la aplicación mientras esperamos una respuesta, el código asíncrono permite que otros procesos continúen ejecutándose.
Imagina un restaurante donde el camarero toma un pedido y se queda esperando junto a la cocina hasta que esté listo, sin atender a otros clientes. Esto sería el equivalente a la programación síncrona. En cambio, la programación asíncrona sería como un camarero que toma múltiples pedidos, los envía a la cocina y continúa atendiendo otros clientes mientras espera que los platos estén listos.
Conceptos fundamentales en Python
Python implementa la asincronía mediante las palabras clave async
y await
. Una función definida con async def
se convierte en una función asíncrona o corrutina, que puede pausar su ejecución y ceder el control a otras tareas.
import asyncio
async def operacion_lenta():
print("Iniciando operación...")
await asyncio.sleep(2) # Simula una operación que tarda 2 segundos
print("Operación completada")
return "Resultado"
La palabra clave await
indica que en ese punto la función puede pausarse y permitir que otras tareas se ejecuten. Solo puede utilizarse dentro de funciones marcadas con async
.
Asincronía en FastAPI
FastAPI está diseñado desde sus cimientos para aprovechar las ventajas de la programación asíncrona. Cuando definimos endpoints con async def
, FastAPI puede manejar múltiples peticiones simultáneamente de forma eficiente.
from fastapi import FastAPI
import asyncio
app = FastAPI()
@app.get("/rapido")
async def endpoint_rapido():
return {"mensaje": "Respuesta inmediata"}
@app.get("/lento")
async def endpoint_lento():
await asyncio.sleep(3) # Simula una operación que tarda 3 segundos
return {"mensaje": "Operación completada después de 3 segundos"}
En este ejemplo, si múltiples usuarios acceden al endpoint /lento
simultáneamente, FastAPI no bloqueará las peticiones. Cada una se procesará de forma concurrente, mejorando significativamente el rendimiento de la aplicación.
Cuándo usar funciones asíncronas
No todas las operaciones requieren asincronía. Las funciones asíncronas son más beneficiosas cuando realizamos operaciones de entrada/salida (I/O) que implican espera:
- Consultas a bases de datos que pueden tardar varios milisegundos
- Llamadas a APIs externas con tiempos de respuesta variables
- Lectura de archivos grandes desde el disco
- Operaciones de red como descargas o uploads
@app.get("/usuarios/{user_id}")
async def obtener_usuario(user_id: int):
# Simula una consulta a base de datos
await asyncio.sleep(0.1) # 100ms de latencia típica de BD
return {"id": user_id, "nombre": "Usuario Ejemplo"}
Diferencias entre sync y async
FastAPI permite definir endpoints tanto síncronos como asíncronos, y cada uno tiene su lugar apropiado:
Endpoints síncronos - para operaciones rápidas y cálculos:
@app.get("/calcular")
def calcular_factorial(n: int):
resultado = 1
for i in range(1, n + 1):
resultado *= i
return {"factorial": resultado}
Endpoints asíncronos - para operaciones con espera:
@app.get("/datos-externos")
async def obtener_datos_externos():
# Simula llamada a API externa
await asyncio.sleep(1)
return {"datos": "Información obtenida de servicio externo"}
Manejo de múltiples operaciones asíncronas
Cuando necesitamos realizar múltiples operaciones asíncronas, Python proporciona herramientas para ejecutarlas de forma concurrente:
@app.get("/datos-completos/{user_id}")
async def obtener_datos_completos(user_id: int):
# Ejecutar múltiples operaciones en paralelo
usuario_task = obtener_usuario_bd(user_id)
pedidos_task = obtener_pedidos_usuario(user_id)
preferencias_task = obtener_preferencias_usuario(user_id)
# Esperar a que todas las operaciones terminen
usuario, pedidos, preferencias = await asyncio.gather(
usuario_task,
pedidos_task,
preferencias_task
)
return {
"usuario": usuario,
"pedidos": pedidos,
"preferencias": preferencias
}
async def obtener_usuario_bd(user_id: int):
await asyncio.sleep(0.1) # Simula consulta BD
return {"id": user_id, "nombre": "Usuario"}
async def obtener_pedidos_usuario(user_id: int):
await asyncio.sleep(0.2) # Simula consulta BD
return [{"id": 1, "producto": "Laptop"}]
async def obtener_preferencias_usuario(user_id: int):
await asyncio.sleep(0.15) # Simula consulta BD
return {"tema": "oscuro", "idioma": "es"}
En este ejemplo, las tres consultas se ejecutan concurrentemente en lugar de secuencialmente, reduciendo el tiempo total de respuesta de 0.45 segundos (0.1 + 0.2 + 0.15) a aproximadamente 0.2 segundos (el tiempo de la operación más lenta).
La asincronía en FastAPI no solo mejora el rendimiento de nuestras aplicaciones, sino que también proporciona una mejor experiencia de usuario al reducir los tiempos de espera y permitir que la aplicación responda de forma más fluida a múltiples peticiones simultáneas.
Lecciones de este módulo de FastAPI
Lecciones de programación del módulo Asincronía del curso de FastAPI.