Saltar a contenido

ReadyAPI

ReadyAPI

ReadyAPI framework, alto rendimiento, fácil de aprender, rápido de programar, listo para producción

Test Coverage Package version Supported Python versions


Documentación: https://readyapi.github.io

Código Fuente: https://github.com/readyapi/readyapi


ReadyAPI es un framework web moderno, rápido (de alto rendimiento), para construir APIs con Python basado en las anotaciones de tipos estándar de Python.

Las características clave son:

  • Rápido: Muy alto rendimiento, a la par con NodeJS y Go (gracias a Starlette y Pydantic). Uno de los frameworks Python más rápidos disponibles.
  • Rápido de programar: Aumenta la velocidad para desarrollar funcionalidades en aproximadamente un 200% a 300%. *
  • Menos bugs: Reduce en aproximadamente un 40% los errores inducidos por humanos (desarrolladores). *
  • Intuitivo: Gran soporte para editores. Autocompletado en todas partes. Menos tiempo depurando.
  • Fácil: Diseñado para ser fácil de usar y aprender. Menos tiempo leyendo documentación.
  • Corto: Minimiza la duplicación de código. Múltiples funcionalidades desde cada declaración de parámetro. Menos bugs.
  • Robusto: Obtén código listo para producción. Con documentación interactiva automática.
  • Basado en estándares: Basado (y completamente compatible) con los estándares abiertos para APIs: OpenAPI (anteriormente conocido como Swagger) y JSON Schema.

* estimación basada en pruebas con un equipo de desarrollo interno, construyendo aplicaciones de producción.

Sponsors

Otros sponsors

Opiniones

"[...] Estoy usando ReadyAPI un montón estos días. [...] De hecho, estoy planeando usarlo para todos los servicios de ML de mi equipo en Microsoft. Algunos de ellos se están integrando en el núcleo del producto Windows y algunos productos de Office."

Kabir Khan - Microsoft (ref)

"Adoptamos el paquete ReadyAPI para crear un servidor REST que pueda ser consultado para obtener predicciones. [para Ludwig]"

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

"Netflix se complace en anunciar el lanzamiento de código abierto de nuestro framework de orquestación de gestión de crisis: Dispatch! [construido con ReadyAPI]"

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

"Estoy súper emocionado con ReadyAPI. ¡Es tan divertido!"


"Honestamente, lo que has construido parece súper sólido y pulido. En muchos aspectos, es lo que quería que Hug fuera; es realmente inspirador ver a alguien construir eso."

Timothy Crosley - creador de Hug (ref)

"Si estás buscando aprender un framework moderno para construir APIs REST, échale un vistazo a ReadyAPI [...] Es rápido, fácil de usar y fácil de aprender [...]"

"Nos hemos cambiado a ReadyAPI para nuestras APIs [...] Creo que te gustará [...]"

Ines Montani - Matthew Honnibal - fundadores de Explosion AI - creadores de spaCy (ref) - (ref)

"Si alguien está buscando construir una API de Python para producción, altamente recomendaría ReadyAPI. Está hermosamente diseñado, es simple de usar y altamente escalable, se ha convertido en un componente clave en nuestra estrategia de desarrollo API primero y está impulsando muchas automatizaciones y servicios como nuestro Ingeniero Virtual TAC."

Deon Pillsbury - Cisco (ref)

Cligenius, el ReadyAPI de las CLIs

Si estás construyendo una aplicación de CLI para ser usada en el terminal en lugar de una API web, revisa Cligenius.

Cligenius es el hermano pequeño de ReadyAPI. Y está destinado a ser el ReadyAPI de las CLIs. ⌨️ 🚀

Requisitos

ReadyAPI se apoya en hombros de gigantes:

Instalación

Crea y activa un entorno virtual y luego instala ReadyAPI:

$ pip install "readyapi[standard]"

---> 100%

Nota: Asegúrate de poner "readyapi[standard]" entre comillas para asegurar que funcione en todas las terminales.

Ejemplo

Créalo

  • Crea un archivo main.py con:
from typing import Union

from readyapi import ReadyAPI

app = ReadyAPI()


@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 typing import Union

from readyapi import ReadyAPI

app = ReadyAPI()


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

$ readyapi dev main.py

 ╭────────── ReadyAPI CLI - Development mode ───────────╮
 │                                                     │
 │  Serving at: http://127.0.0.1:8000                  │
 │                                                     │
 │  API docs: http://127.0.0.1:8000/docs               │
 │                                                     │
 │  Running in development mode, for production use:   │
 │                                                     │
 │  readyapi run                                        │
 │                                                     │
 ╰─────────────────────────────────────────────────────╯

INFO:     Will watch for changes in these directories: ['/home/user/code/awesomeapp']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [2248755] using WatchFiles
INFO:     Started server process [2248757]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
Acerca del comando readyapi dev main.py...

El comando readyapi dev lee tu archivo main.py, detecta la app ReadyAPI en él y arranca un servidor usando Uvicorn.

Por defecto, readyapi dev comenzará con auto-recarga habilitada para el desarrollo local.

Puedes leer más sobre esto en la documentación del CLI de ReadyAPI.

Revísalo

Abre tu navegador en http://127.0.0.1:8000/items/5?q=somequery.

Verás el response JSON como:

{"item_id": 5, "q": "somequery"}

Ya creaste una API que:

  • Recibe requests HTTP en los paths / y /items/{item_id}.
  • Ambos paths toman operaciones GET (también conocidas como métodos HTTP).
  • El path /items/{item_id} tiene un parámetro de path item_id que debe ser un int.
  • El path /items/{item_id} tiene un parámetro de query q opcional que es un str.

Documentación interactiva de la API

Ahora ve a http://127.0.0.1:8000/docs.

Verás la documentación interactiva automática de la API (proporcionada por Swagger UI):

Swagger UI

Documentación de API Alternativa

Y ahora, ve a http://127.0.0.1:8000/redoc.

Verás la documentación alternativa automática (proporcionada por ReDoc):

ReDoc

Actualización del Ejemplo

Ahora modifica el archivo main.py para recibir un body desde un request PUT.

Declara el body usando tipos estándar de Python, gracias a Pydantic.

from typing import Union

from readyapi import ReadyAPI
from pydantic import BaseModel

app = ReadyAPI()


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 readyapi dev debería recargarse automáticamente.

Actualización de la Documentación Interactiva de la API

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 clic en el botón "Try it out", te permite llenar los parámetros e interactuar directamente con la API:

Swagger UI interaction

  • Luego haz clic en el botón "Execute", la interfaz de usuario se comunicará con tu API, enviará los parámetros, obtendrá los resultados y los mostrará en la pantalla:

Swagger UI interaction

Actualización de la Documentación Alternativa de la API

Y ahora, ve a http://127.0.0.1:8000/redoc.

  • La documentación alternativa también reflejará el nuevo parámetro de query y body:

ReDoc

Resumen

En resumen, declaras una vez los tipos de parámetros, body, etc. como parámetros de función.

Lo haces con tipos estándar modernos de Python.

No tienes que aprender una nueva sintaxis, los métodos o clases de un paquete específico, etc.

Solo Python estándar.

Por ejemplo, para un int:

item_id: int

o para un modelo Item más complejo:

item: Item

...y con esa única declaración obtienes:

  • Soporte para editores, incluyendo:
    • Autocompletado.
    • Chequeo de tipos.
  • Validación de datos:
    • Errores automáticos y claros cuando los datos son inválidos.
    • Validación incluso para objetos JSON profundamente anidados.
  • Conversión de datos de entrada: de la red a los datos y tipos de Python. Leyendo desde:
    • JSON.
    • Parámetros de path.
    • Parámetros de query.
    • Cookies.
    • Headers.
    • Forms.
    • Archivos.
  • Conversión de datos de salida: convirtiendo de datos y tipos de Python a datos de red (como JSON):
    • Convertir tipos de Python (str, int, float, bool, list, etc).
    • Objetos datetime.
    • Objetos UUID.
    • Modelos de base de datos.
    • ...y muchos más.
  • Documentación interactiva automática de la API, incluyendo 2 interfaces de usuario alternativas:
    • Swagger UI.
    • ReDoc.

Volviendo al ejemplo de código anterior, ReadyAPI:

  • Validará que haya un item_id en el path para requests GET y PUT.
  • Validará que el item_id sea del tipo int para requests GET y PUT.
    • Si no lo es, el cliente verá un error útil y claro.
  • Comprobará si hay un parámetro de query opcional llamado q (como en http://127.0.0.1:8000/items/foo?q=somequery) para requests GET.
    • Como el parámetro q está declarado con = None, es opcional.
    • Sin el None sería requerido (como lo es el body en el caso con PUT).
  • Para requests PUT a /items/{item_id}, leerá el body como JSON:
    • Comprobará que tiene un atributo requerido name que debe ser un str.
    • Comprobará que tiene un atributo requerido price que debe ser un float.
    • Comprobará que tiene un atributo opcional is_offer, que debe ser un bool, si está presente.
    • Todo esto también 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 cliente, para muchos lenguajes.
  • Proporcionará 2 interfaces web de documentación interactiva directamente.

Solo tocamos los conceptos básicos, pero ya te haces una idea de cómo funciona todo.

Intenta cambiar la línea con:

    return {"item_name": item.name, "item_id": item_id}

...desde:

        ... "item_name": item.name ...

...a:

        ... "item_price": item.price ...

...y observa cómo tu editor autocompleta los atributos y conoce sus tipos:

editor support

Para un ejemplo más completo incluyendo más funcionalidades, ve al Tutorial - Guía del Usuario.

Alerta de spoilers: el tutorial - guía del usuario incluye:

  • Declaración de parámetros desde otros lugares diferentes como: headers, cookies, campos de formulario y archivos.
  • Cómo establecer restricciones de validación como maximum_length o regex.
  • Un sistema de Inyección de Dependencias muy poderoso y fácil de usar.
  • Seguridad y autenticación, incluyendo soporte para OAuth2 con tokens JWT y autenticación HTTP Basic.
  • Técnicas más avanzadas (pero igualmente fáciles) para declarar modelos JSON profundamente anidados (gracias a Pydantic).
  • Integración con GraphQL usando Strawberry y otros paquetes.
  • Muchas funcionalidades extra (gracias a Starlette) como:
    • WebSockets
    • pruebas extremadamente fáciles basadas en HTTPX y pytest
    • CORS
    • Sesiones de Cookies
    • ...y más.

Rendimiento

Benchmarks independientes de TechEmpower muestran aplicaciones ReadyAPI ejecutándose bajo Uvicorn como uno de los frameworks Python más rápidos disponibles, solo por debajo de Starlette y Uvicorn (usados internamente por ReadyAPI). (*)

Para entender más sobre esto, ve la sección Benchmarks.

Dependencias

ReadyAPI depende de Pydantic y Starlette.

Dependencias standard

Cuando instalas ReadyAPI con pip install "readyapi[standard]" viene con el grupo standard de dependencias opcionales:

Usadas por Pydantic:

Usadas por Starlette:

  • httpx - Requerido si deseas usar el TestClient.
  • jinja2 - Requerido si deseas usar la configuración de plantilla predeterminada.
  • python-multipart - Requerido si deseas soportar "parsing" de forms, con request.form().

Usadas por ReadyAPI / Starlette:

  • uvicorn - para el servidor que carga y sirve tu aplicación. Esto incluye uvicorn[standard], que incluye algunas dependencias (por ejemplo, uvloop) necesarias para servir con alto rendimiento.
  • readyapi-cli - para proporcionar el comando readyapi.

Sin Dependencias standard

Si no deseas incluir las dependencias opcionales standard, puedes instalar con pip install readyapi en lugar de pip install "readyapi[standard]".

Dependencias Opcionales Adicionales

Existen algunas dependencias adicionales que podrías querer instalar.

Dependencias opcionales adicionales de Pydantic:

Dependencias opcionales adicionales de ReadyAPI:

  • orjson - Requerido si deseas usar ORJSONResponse.
  • ujson - Requerido si deseas usar UJSONResponse.

Licencia

Este proyecto tiene licencia bajo los términos de la licencia MIT.