FastAPI
FastAPI framework, alto desempeño, fácil de aprender, rápido de programar, listo para producción
Documentación: https://fastapi.tiangolo.com
Código Fuente: https://github.com/tiangolo/fastapi
FastAPI es un web framework moderno y rápido (de alto rendimiento) para construir APIs con Python 3.8+ basado en las anotaciones de tipos estándar de Python.
Sus características principales son:
-
Rapidez: Alto rendimiento, a la par con NodeJS y Go (gracias a Starlette y Pydantic). Uno de los frameworks de Python más rápidos.
-
Rápido de programar: Incrementa la velocidad de desarrollo entre 200% y 300%. *
- Menos errores: Reduce los errores humanos (de programador) aproximadamente un 40%. *
- Intuitivo: Gran soporte en los editores con auto completado en todas partes. Gasta menos tiempo debugging.
- Fácil: Está diseñado para ser fácil de usar y aprender. Gastando menos tiempo leyendo documentación.
- Corto: Minimiza la duplicación de código. Múltiples funcionalidades con cada declaración de parámetros. Menos errores.
- Robusto: Crea código listo para producción con documentación automática interactiva.
- Basado en estándares: Basado y totalmente compatible con los estándares abiertos para APIs: OpenAPI (conocido previamente como Swagger) y JSON Schema.
* Esta estimación está basada en pruebas con un equipo de desarrollo interno construyendo aplicaciones listas para producción.
Sponsors¶
Opiniones¶
"[...] I'm using FastAPI a ton these days. [...] I'm actually planning to use it for all of my team's ML services at Microsoft. Some of them are getting integrated into the core Windows product and some Office products."
"We adopted the FastAPI library to spawn a REST server that can be queried to obtain predictions. [for Ludwig]"
"Netflix is pleased to announce the open-source release of our crisis management orchestration framework: Dispatch! [built with FastAPI]"
"I’m over the moon excited about FastAPI. It’s so fun!"
"Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted Hug to be - it's really inspiring to see someone build that."
"If you're looking to learn one modern framework for building REST APIs, check out FastAPI [...] It's fast, easy to use and easy to learn [...]"
"We've switched over to FastAPI for our APIs [...] I think you'll like it [...]"
Typer, el FastAPI de las CLIs¶
Si estás construyendo un app de CLI para ser usada en la terminal en vez de una API web, fíjate en Typer.
Typer es el hermano menor de FastAPI. La intención es que sea el FastAPI de las CLIs. ⌨️ 🚀
Requisitos¶
Python 3.8+
FastAPI está sobre los hombros de gigantes:
Instalación¶
$ pip install fastapi
---> 100%
También vas a necesitar un servidor ASGI para producción cómo Uvicorn o Hypercorn.
$ pip install "uvicorn[standard]"
---> 100%
Ejemplo¶
Créalo¶
- Crea un archivo
main.py
con:
from fastapi import FastAPI
from typing import Union
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
O usa async def
...
Si tu código usa async
/ await
, usa async def
:
from fastapi import FastAPI
from typing import Union
app = FastAPI()
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
Nota:
Si no lo sabes, revisa la sección "¿Con prisa?" sobre async
y await
en la documentación.
Córrelo¶
Corre el servidor con:
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Waiting for application startup.
INFO: Application startup complete.
Sobre el comando uvicorn main:app --reload
...
El comando uvicorn main:app
se refiere a:
main
: el archivomain.py
(el"modulo" de Python).app
: el objeto creado dentro demain.py
con la líneaapp = FastAPI()
.--reload
: hace que el servidor se reinicie después de cambios en el código. Esta opción solo debe ser usada en desarrollo.
Revísalo¶
Abre tu navegador en http://127.0.0.1:8000/items/5?q=somequery.
Verás la respuesta de JSON cómo:
{"item_id": 5, "q": "somequery"}
Ya creaste una API que:
- Recibe HTTP requests en los paths
/
y/items/{item_id}
. - Ambos paths toman operaciones
GET
(también conocido como HTTP methods). - El path
/items/{item_id}
tiene un path parameteritem_id
que debería ser unint
. - El path
/items/{item_id}
tiene unstr
query parameterq
opcional.
Documentación interactiva de APIs¶
Ahora ve a http://127.0.0.1:8000/docs.
Verás la documentación automática e interactiva de la API (proveída por Swagger UI):
Documentación alternativa de la API¶
Ahora, ve a http://127.0.0.1:8000/redoc.
Ahora verás la documentación automática alternativa (proveída por ReDoc):
Mejora al ejemplo¶
Ahora modifica el archivo main.py
para recibir un body del PUT
request.
Declara el body usando las declaraciones de tipo estándares de Python gracias a Pydantic.
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Union
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: Union[bool, None] = None
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
El servidor debería recargar automáticamente (porque añadiste --reload
al comando uvicorn
que está más arriba).
Mejora a la documentación interactiva de APIs¶
Ahora ve a http://127.0.0.1:8000/docs.
- La documentación interactiva de la API se actualizará automáticamente, incluyendo el nuevo body:
- Haz click en el botón de "Try it out" que te permite llenar los parámetros e interactuar directamente con la API:
- Luego haz click en el botón de "Execute". La interfaz de usuario se comunicará con tu API, enviará los parámetros y recibirá los resultados para mostrarlos en pantalla:
Mejora a la documentación alternativa de la API¶
Ahora, ve a http://127.0.0.1:8000/redoc.
- La documentación alternativa también reflejará el nuevo parámetro de query y el body:
Resumen¶
En resumen, declaras los tipos de parámetros, body, etc. una vez como parámetros de la función.
Lo haces con tipos modernos estándar de Python.
No tienes que aprender una sintaxis nueva, los métodos o clases de una library específica, etc.
Solo Python 3.8+ estándar.
Por ejemplo, para un int
:
item_id: int
o para un modelo más complejo de Item
:
item: Item
...y con esa única declaración obtienes:
- Soporte del editor incluyendo:
- Auto completado.
- Anotaciones de tipos.
- Validación de datos:
- Errores automáticos y claros cuándo los datos son inválidos.
- Validación, incluso para objetos JSON profundamente anidados.
- Conversión de datos de input: viniendo de la red a datos y tipos de Python. Leyendo desde:
- JSON.
- Path parameters.
- Query parameters.
- Cookies.
- Headers.
- Formularios.
- Archivos.
- Conversión de datos de output: convirtiendo de datos y tipos de Python a datos para la red (como JSON):
- Convertir tipos de Python (
str
,int
,float
,bool
,list
, etc). - Objetos
datetime
. - Objetos
UUID
. - Modelos de bases de datos.
- ...y muchos más.
- Convertir tipos de Python (
- Documentación automática e interactiva incluyendo 2 interfaces de usuario alternativas:
- Swagger UI.
- ReDoc.
Volviendo al ejemplo de código anterior, FastAPI va a:
- Validar que existe un
item_id
en el path para requests usandoGET
yPUT
. - Validar que el
item_id
es del tipoint
para requests de tipoGET
yPUT
.- Si no lo es, el cliente verá un mensaje de error útil y claro.
- Revisar si existe un query parameter opcional llamado
q
(cómo enhttp://127.0.0.1:8000/items/foo?q=somequery
) para requests de tipoGET
.- Como el parámetro
q
fue declarado con= None
es opcional. - Sin el
None
sería obligatorio (cómo lo es el body en el caso conPUT
).
- Como el parámetro
- Para requests de tipo
PUT
a/items/{item_id}
leer el body como JSON:- Revisar si tiene un atributo requerido
name
que debe ser unstr
. - Revisar si tiene un atributo requerido
price
que debe ser unfloat
. - Revisar si tiene un atributo opcional
is_offer
, que debe ser unbool
si está presente. - Todo esto funcionaría para objetos JSON profundamente anidados.
- Revisar si tiene un atributo requerido
- Convertir de y a JSON automáticamente.
- Documentar todo con OpenAPI que puede ser usado por:
- Sistemas de documentación interactiva.
- Sistemas de generación automática de código de cliente para muchos lenguajes.
- Proveer directamente 2 interfaces de documentación web interactivas.
Hasta ahora, escasamente vimos lo básico pero ya tienes una idea de cómo funciona.
Intenta cambiando la línea a:
return {"item_name": item.name, "item_id": item_id}
...de:
... "item_name": item.name ...
...a:
... "item_price": item.price ...
... y mira como el editor va a auto-completar los atributos y sabrá sus tipos:
Para un ejemplo más completo que incluye más características ve el Tutorial - Guía de Usuario.
Spoiler alert: el Tutorial - Guía de Usuario incluye:
- Declaración de parámetros en otros lugares diferentes cómo los: headers, cookies, formularios y archivos.
- Cómo agregar requisitos de validación cómo
maximum_length
oregex
. - Un sistema de Dependency Injection poderoso y fácil de usar.
- Seguridad y autenticación incluyendo soporte para OAuth2 con JWT tokens y HTTP Basic auth.
- Técnicas más avanzadas, pero igual de fáciles, para declarar modelos de JSON profundamente anidados (gracias a Pydantic).
- Muchas características extra (gracias a Starlette) como:
- WebSockets
- GraphQL
- pruebas extremadamente fáciles con HTTPX y
pytest
- CORS
- Cookie Sessions
- ...y mucho más.
Rendimiento¶
Benchmarks independientes de TechEmpower muestran que aplicaciones de FastAPI corriendo con Uvicorn cómo uno de los frameworks de Python más rápidos, únicamente debajo de Starlette y Uvicorn (usados internamente por FastAPI). (*)
Para entender más al respecto revisa la sección Benchmarks.
Dependencias Opcionales¶
Usadas por Pydantic:
email_validator
- para validación de emails.
Usados por Starlette:
httpx
- Requerido si quieres usar elTestClient
.jinja2
- Requerido si quieres usar la configuración por defecto de templates.python-multipart
- Requerido si quieres dar soporte a "parsing" de formularios, conrequest.form()
.itsdangerous
- Requerido para dar soporte aSessionMiddleware
.pyyaml
- Requerido para dar soporte alSchemaGenerator
de Starlette (probablemente no lo necesites con FastAPI).graphene
- Requerido para dar soporte aGraphQLApp
.ujson
- Requerido si quieres usarUJSONResponse
.
Usado por FastAPI / Starlette:
uvicorn
- para el servidor que carga y sirve tu aplicación.orjson
- Requerido si quieres usarORJSONResponse
.
Puedes instalarlos con pip install fastapi[all]
.
Licencia¶
Este proyecto está licenciado bajo los términos de la licencia del MIT.