Los 5 mejores marcos web asíncronos para Python

La programación asincrónica es ahora un ciudadano de primera clase en Python. Si eres un desarrollador web, ¡hay marcos increíbles entre los que puedes elegir!

Al momento de escribir, asincrónico ya no es solo una palabra de moda en la comunidad de Python. Con el lanzamiento de su asíncio biblioteca en la versión 3.5, Python reconoció el impacto de Node.js en el desarrollo web e introdujo dos nuevas palabras clave en el lenguaje: async y await. Este fue un gran problema porque el lenguaje Python es extremadamente cauteloso a la hora de expandir la sintaxis central a menos que haya una necesidad apremiante, lo que solo indica cuán fundamentalmente importantes los desarrolladores de Python consideraron las capacidades asincrónicas.

Como resultado, se abrieron las compuertas de la programación asincrónica: las bibliotecas nuevas y antiguas comenzaron a utilizar la función de corrutinas, los marcos asincrónicos explotaron en popularidad y todavía se están escribiendo nuevos en la actualidad. El rendimiento a la par o mejor que el de Node.js no es inaudito y, a menos que sus patrones de carga impliquen muchas tareas de uso intensivo de la CPU, no hay ninguna razón por la que no pueda realizar unos miles de solicitudes por segundo.

¡Pero basta de motivación!

Analicemos el panorama actual de Python y veamos algunos de los principales marcos asincrónicos.

Tornado

Asombrosamente, Tornado no es un marco nuevo en absoluto. Su lanzamiento inicial fue en 2009 (hace exactamente diez años, al momento de escribir este artículo) y desde entonces, su enfoque ha sido proporcionar una programación asíncrona sólida como una roca con alta concurrencia.

Tornado no es un marco web fundamentalmente. Es una colección de módulos asincrónicos, que también se utilizan para construir el módulo del marco web. Más específicamente, estos módulos son:

  • Corrutinas y otras primitivas (tornado.gen, tornado.locks, tornado.queues, etc.)
  • Módulos de red (tornado.ioloop, tornado.iostream, etc.)
  • Servidores y clientes asíncronos (tornado.httpserver, tornado.httpclient, etc.)

Estos se han combinado para producir los módulos del marco final: tornado.web, tornado.routing, tornado.template, etc.

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
    ])

if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()

Tornado tiene seguidores fuertes y comprometidos en la comunidad de Python y es utilizado por arquitectos experimentados para construir sistemas altamente capaces. Es un marco que durante mucho tiempo ha tenido la respuesta a los problemas de concurrencia, pero tal vez no se convirtió en la corriente principal, ya que no es compatible con el estándar WSGI y fue demasiado para comprar (recuerde que la mayor parte de las bibliotecas de Python todavía son síncronas ).

Sanic

Sanic es un marco «moderno» en el verdadero sentido de la palabra: no es compatible con la versión de Python anterior a la 3.6, es compatible con la sintaxis simple y universal async/await lista para usar y, como resultado, no le hace leer mucho de documentación y tenga en mente los casos extremos antes de que pueda escribir su primer controlador HTTP.

Como resultado, la sintaxis resultante es bastante agradable (al menos en mi opinión); se parece al código que escribiría con cualquier otro microframework (Flask, CherryPy, por ejemplo) con solo algunos asincrónicos salpicados:

from sanic import Sanic
from sanic.response import json

app = Sanic()

@app.route("/")
async def test(request):
    return json({"hello": "world"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000)

Sanic es posiblemente el marco asíncrono más popular y querido en el mundo de Python. Tiene casi todas las funciones que desearía para sus proyectos: enrutamiento, middleware, cookies, control de versiones, blueprints, vistas basadas en clases, archivos estáticos, transmisión, sockets, etc., y lo que no ofrece de fábrica. Se pueden agregar plantillas, soporte de bases de datos, E/S de archivos, colas, ya que hay suficientes bibliotecas asíncronas para estos a partir de hoy.

víbora

víbora es un primo cercano de Sanic, excepto que está obsesionado con convertirse en el servidor web de Python más rápido que existe. De hecho, la primera visita a su sitio web lo recibe con una comparación de marcos:

Como puede ver, Vibora afirma ser varias veces más rápido que los marcos clásicos y más del doble de rápido que Sanic, su competidor más cercano. Por supuesto, los puntos de referencia deben tomarse con pinzas. 🙂

Aunque en sintaxis y características, Vibora es comparable a Sanic (o tal vez incluso un poco mejor, ya que incluye bibliotecas populares y cosas como las plantillas están disponibles listas para usar), consideraría que Sanic es más maduro, ya que ha existido por más tiempo y ha una comunidad más grande.

from vibora import Vibora, JsonResponse

app = Vibora()

@app.route('/')
async def home():
    return JsonResponse({'hello': 'world'})

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=8000)

Sin embargo, si eres un adicto al rendimiento, Vibora podría flotar en tu bote. Dicho esto, al momento de escribir, Vibora está realizando una reescritura completa para volverse aún más rápido, y el Enlace a su versión de rendimiento dice que está en «desarrollo pesado». Va a ser una decepción para aquellos que eligieron Vibora antes y pronto deben enfrentar cambios importantes, pero bueno, son los primeros días en el mundo asíncrono de Python, y nadie espera que las cosas sean estables.

Cuarto de galón

Si te gusta desarrollar en Flask pero te arrepientes de la falta de soporte asíncrono, disfrutarás Cuarto de galón mucho.

Quart cumple con la ASGI estándar, que es un sucesor del famoso estándar WSGI y ofrece soporte asíncrono. Lo interesante de Quart es que no solo es similar a Flask, ¡sino que en realidad cumple con la API de Flask! El autor de este marco quería preservar la sensación de Flask y simplemente agregarle soporte asincrónico, WebSockets y HTTP 2. Como resultado, puede aprender Quart directamente desde la documentación de Flask, solo teniendo en cuenta que las funciones en Quart son asíncronas.

from quart import Quart

app = Quart(__name__)

@app.route('/')
async def hello():
    return 'hello'

app.run()

Se siente (casi) exactamente como Flask, ¿no es así?

Dado que Quart es una evolución de Flask, todas las funciones dentro de Flask están disponibles: enrutamiento, middleware, sesiones, plantillas, blueprints, etc. De hecho, incluso puede usar las extensiones de Flask directamente dentro de Quart. Una pega es que Python 3.7+ solo es compatible, pero, entonces, si no está ejecutando la última versión de Python, tal vez async no sea el camino correcto. 🙂

La documentación es realmente deficiente si no tiene experiencia previa con Flask, pero puedo recomendar Quart ya que es probablemente el único marco asincrónico que se acerca a su lanzamiento 1.0 pronto.

API rápida

El último (pero más impresionante) marco de esta lista es API rápida. No, no es un marco solo para API; de hecho, FastAPI parece ser el marco más rico en funciones y documentación que encontré al investigar los marcos Python asíncronos.

Es interesante notar que el autor del marco estudió varios otros marcos en profundidad, desde los contemporáneos como Django hasta los modernos como Sanic, además de analizar tecnologías en NestJS (un marco web Node.js, Typescript). Su filosofía de desarrollo y extensas comparaciones se pueden leer aquí.

La sintaxis es bastante agradable; incluso se puede argumentar que es mucho más agradable que los otros marcos que hemos encontrado:

rom fastapi import FastAPI

app = FastAPI()

@app.get("/users/me")
async def read_user_me():
    return {"user_id": "the current user"}

@app.get("/users/{user_id}")
async def read_user(user_id: str):
    return {"user_id": user_id}

Y ahora, la lista de características geniales que hacen que FastAPI eclipse a otros marcos:

Generación automática de documentos de API: tan pronto como se hayan escrito sus puntos finales, puede jugar con la API utilizando una interfaz de usuario compatible con los estándares. Se admiten SwaggerUI, ReDoc y otros.

El marco también realiza la documentación automática del modelo de datos con JSON Schema.

Desarrollo moderno: sí, la palabra «moderno» se usa mucho, pero descubrí que FastAPI realmente cumple con lo que dice. La inyección de dependencia y la sugerencia de tipo son ciudadanos de primera clase, ya que no solo aplican buenos principios de codificación, sino que también evitan errores y confusiones a largo plazo.

Amplia documentación: no sé ustedes, pero yo soy un completo fanático de la buena documentación. Y en esta área, FastAPI gana sin lugar a dudas. Tiene páginas y páginas de documentos que explican casi cada pequeña sutileza y «¡cuidado!» Momentos para desarrolladores de todos los niveles. Siento un claro «corazón y alma» en los documentos aquí, y la única comparación que puedo encontrar son los documentos de Django (sí, ¡los documentos de FastAPI son tan buenos!).

Más allá de lo básico: FastAPI tiene soporte para WebSockets, Streaming, así como GraphQL, además de tener todos los ayudantes tradicionales como CORS, sesiones, cookies, etc.

¿Y qué hay del rendimiento? Bueno, FastAPI se basa en la increíble biblioteca Starlette, lo que da como resultado un rendimiento que coincide con Node y, en algunos casos, ¡incluso con Go! Considerándolo todo, realmente tengo la sensación de que FastAPI va a competir como el mejor marco asíncrono para Python.

Conclusión

Están sucediendo muchas cosas en el panorama asíncrono de Python en estos días. Están apareciendo nuevos marcos, se están reescribiendo los antiguos y se están desarrollando bibliotecas para que coincidan con el comportamiento asíncrono. Si bien Python tiene soporte incorporado para un bucle de eventos y es posible hacer que partes de su aplicación sean asíncronas, puede optar por ir con todo y construir sobre uno de los marcos aquí. Solo asegúrese de tener en cuenta el largo plazo: varios de los marcos asíncronos de Python que existen están en etapas iniciales y están evolucionando rápidamente, lo que perjudicará su proceso de desarrollo y aumentará los costos comerciales. ¡La precaución es clave!

Pero todo dicho y hecho; Python está listo para la producción para ofrecer un rendimiento ligero cuando se trata de marcos web. Si durante tanto tiempo ha estado pensando en migrar a Node, ¡ahora no es necesario! 🙂

¿Suena bien? Maestro Python hoy!