Saltar a contenido

FastAPI

FastAPI

FastAPI framework, alto desempeño, fácil de aprender, rápido de programar, listo para producción

Test Coverage Package version


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 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

Otros 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."

Kabir Khan - Microsoft (ref)

"We adopted the FastAPI library to spawn a REST server that can be queried to obtain predictions. [for Ludwig]"

Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)

"Netflix is pleased to announce the open-source release of our crisis management orchestration framework: Dispatch! [built with FastAPI]"

Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)

"I’m over the moon excited about FastAPI. It’s so fun!"

Brian Okken - Python Bytes podcast host (ref)

"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."

Timothy Crosley - Hug creator (ref)

"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 [...]"

Ines Montani - Matthew Honnibal - Explosion AI founders - spaCy creators (ref) - (ref)

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

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 archivo main.py (el"modulo" de Python).
  • app: el objeto creado dentro de main.py con la línea app = 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 parameter item_id que debería ser un int.
  • El path /items/{item_id} tiene un str query parameter q 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):

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):

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:

Swagger UI

  • Haz click en el botón de "Try it out" que te permite llenar los parámetros e interactuar directamente con la API:

Swagger UI interaction

  • 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:

Swagger UI interaction

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:

ReDoc

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 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.
  • 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 usando GET y PUT.
  • Validar que el item_id es del tipo int para requests de tipo GET y PUT.
    • 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 en http://127.0.0.1:8000/items/foo?q=somequery) para requests de tipo GET.
    • 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 con PUT).
  • Para requests de tipo PUT a /items/{item_id} leer el body como JSON:
    • Revisar si tiene un atributo requerido name que debe ser un str.
    • Revisar si tiene un atributo requerido price que debe ser un float.
    • Revisar si tiene un atributo opcional is_offer, que debe ser un boolsi está presente.
    • Todo esto funcionaría para objetos JSON profundamente anidados.
  • 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:

soporte de editor

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 o regex.
  • 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:

Usados por Starlette:

  • httpx - Requerido si quieres usar el TestClient.
  • jinja2 - Requerido si quieres usar la configuración por defecto de templates.
  • python-multipart - Requerido si quieres dar soporte a "parsing" de formularios, con request.form().
  • itsdangerous - Requerido para dar soporte a SessionMiddleware.
  • pyyaml - Requerido para dar soporte al SchemaGenerator de Starlette (probablemente no lo necesites con FastAPI).
  • graphene - Requerido para dar soporte a GraphQLApp.

Usado por FastAPI / Starlette:

  • uvicorn - para el servidor que carga y sirve tu aplicación.
  • orjson - Requerido si quieres usar ORJSONResponse.
  • ujson - Requerido si quieres usar UJSONResponse.

Puedes instalarlos con pip install fastapi[all].

Licencia

Este proyecto está licenciado bajo los términos de la licencia del MIT.