https://d226lax1qjow5r.cloudfront.net/blog/blogposts/the-ultimate-face-off-flask-vs-fastapi/flask-vs-fastapi_1200x600.png

El enfrentamiento definitivo: Flask contra FastAPI

Publicado el July 30, 2021

Tiempo de lectura: 7 minutos

Elegir un marco no es fácil, y por eso estoy aquí para ayudarte a librarte del quebradero de cabeza.

¿Por qué comparar Flask y FastAPI?

Son similares. Ambos son microframeworks Python despojados sin las campanas y silbatos hinchados, lo que significa un tiempo de desarrollo más rápido y más flexibilidad. Además, ambos se utilizan para crear API y aplicaciones web.

También son diferentes. Flask está más probado, por lo tanto ligeramente más fiable, y es ampliamente utilizado. FastAPI es un framework más nuevo y moderno conocido por su velocidad con un montón de soporte integrado como Pydantic y SwaggerUI.

Ahora que ya conoces mejor cada marco, ¡que empiece nuestro cara a cara!

Instalación

A veces, lo más difícil de aprender algo nuevo es empezar. Por eso empezaremos con la instalación.

Es relativamente sencillo instalar tanto Flask como FastAPI usando el instalador favorito de Python, pip. También es una buena práctica instalar ambos dentro de un entorno virtual, un entorno aislado para cada uno de tus proyectos Python que elimina los errores de colisión.

Frasco

$ pip install flask

FastAPI

$ pip install fastapi uvicorn

Conclusión: Observe que instala FastAPI con Uvicorn. Piense en Uvicorn como un servidor ultrarrápido que permite que sus aplicaciones funcionen más rápido.

Aplicación Hola Mundo

Si sólo has escrito una línea de código en toda tu vida, apuesto a que era algo como esto:

print(“Hello World”)

Es como aprender otro idioma, por ejemplo mandarín. Hay un sistema llamado Pinyin, que transcribe los caracteres chinos al inglés para que la gente pueda pronunciarlos. Está diseñado para que te pongas manos a la obra rápidamente, como si fuera una aplicación de Hello World.

Veamos qué aspecto tiene una aplicación hola mundo tanto en Flask como en FastAPI.

Flask < 2.0

# inside of a Python .py file

from flask import Flask

app = Flask(__name__)

@app.route("/", methods=\[“GET”])
def home():
    return {"Hello": "World"}

if __name__ == "__main__":

    app.run()

Flask 2.0

from flask import Flask

app = Flask(__name__)

@app.get("/")
def home():
    return {"Hello": "World"}

if __name__ == "__main__":

    app.run()

FastAPI

# inside of a Python .py file

import uvicorn

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def home():
    return {"Hello": "World"}

if __name__ == "__main__":

    uvicorn.run("main:app")

Conclusión: En las versiones más recientes de Flask, se puede utilizar el método @app.get() y @app.post() como atajos para el enrutamiento. La forma anterior de usar @app.route() requería que pasaras tus verbos HTTP a una lista de métodos de la forma methods=\[“GET”, “POST”].

Nota: Flask hace un GET por defecto, por lo que no es necesario especificarlo en la lista de métodos.
Estos métodos también vienen en FastAPI con soporte para las siguientes rutas decoradas para cada método HTTP:

  • @app.get()

  • @app.post()

  • @app.put()

  • @app.delete()

En desarrollo

Una vez que tengas escrita tu aplicación "Hola Mundo", querrás ejecutarla primero en desarrollo -o localmente en tu máquina- antes de ponerla en producción para que todo el mundo la vea. Si tu aplicación no funciona como esperabas, la gente se asustará. Usted quiere minimizar el freakout.

Así que en tu terminal, ejecuta estos comandos:

Frasco

$ export FLASK_APP=app.py

$ export FLASK_ENV=development

$ flask run

FastAPI

$ uvicorn main:app --reload

Conclusión: FastAPI utiliza la Recarga en Caliente, que mantiene la aplicación en ejecución mientras realizas cambios en el código. Por lo tanto, no tienes que reiniciar el servidor de desarrollo. Con Flask, necesitas un comando de terminal extra: export FLASK_ENV=developmentque te permite hacer cambios en el código sin reiniciar el servidor de desarrollo.

Métodos HTTP

En el ejemplo de Hola Mundo, vimos cómo se ve un GET en Flask y FastAPI, así que ahora vamos a echar un vistazo más de cerca a un método POST.

Flask < 2.0

@app.route("/teams", methods=["POST"])
def create_team():
    team = {

        "team_name": "Phoenix Suns",
        "players": [

            {

                  "name": "Chris Paul",
                  "age": 36

            }

        ]

    }

    teams.append(team)
    return (jsonify(teams))

Flask 2.0

@app.post("/teams")
def create_team():
    team = {

        "team_name": "Phoenix Suns",
        "players": [

            {

                  "name": "Chris Paul",
                  "age": 36

            }

        ]

    }

    teams.append(team)
    return (jsonify(teams))

FastAPI

@app.post("/teams")
def create_team():
    team = {

        "team_name": "Phoenix Suns",
        "players": [

            {

                  "name": "Chris Paul",
                  "age": 36

            }

        ]

    }

    teams.append(team)
    return {'teams':teams}

Conclusión: Flask 2.0 y FastAPI se parecen mucho cuando se hace un método POST. El truco está en ver cómo se crean los nuevos datos.

Con Flask, tendrás que utilizar una herramienta como Postman actuando como cliente, para que puedas ver tus peticiones POST y los datos que has creado en formato JSON.
FastAPI viene con Pydantic y SwaggerUI fuera de la caja, lo que le permite utilizar la documentación automática para interactuar con sus solicitudes desde el navegador, incluidas las solicitudes POST.

Flask también puede usar documentación automática, pero tendrás que instalarla usando flask-swagger. También hay mucha configuración involucrada para hacer que funcione. Veamos cómo ver tus peticiones POST en FastAPI en la siguiente sección.

Documentación automática

Si cree en la magia, le encantará Documentación Automática.

FastAPI se basa en Pydantic, un framework para modelar y validar objetos fácilmente. Viene fuera de la caja, por lo que no es necesario instalarlo. Pydantic elimina el dolor de escribir constructores, y obtienes todos los métodos mágicos. Pydantic también hace validación de datos que muestra errores más amigables y utiliza sugerencias de tipo python, reduciendo el tiempo de depuración. Para acceder a su documentación automática, asegúrese de que su servidor de desarrollo se está ejecutando, a continuación, vaya a su localhost y el puerto en el que se está ejecutando su aplicación:

http://127.0.0.1:8000/docs

Verá su solicitud POST como en el ejemplo siguiente; si utiliza otros métodos HTTP, también serán visibles.

FastAPI Python automatic documentation POST request using PydanticFastAPI Python automatic documentation POST request using Pydantic

Hagamos algo mucho más genial para que podamos ver la belleza de la documentación automática. Digamos que tenemos este código en FastAPI:

FastAPI

from pydantic import BaseModel

app = FastAPI()

class Player(BaseModel):
    player_name: str
    player_team: str
    player_age: int

@app.post("/teams")
def create_team(request: Player):
    return {'teams':request}

Tenga en cuenta que para utilizar Pydantic, tiene que importar el archivo BaseModel que heredará la clase Player heredará. También estamos declarando variables como type hints dentro de nuestra clase y devolviendo un diccionario en nuestra petición POST.

Cuando abra su documentación automática, verá un Esquema. Este esquema es un esqueleto para su modelo con variables, donde se puede ver qué campos son obligatorios y cuáles son opcionales.

FastAPI Python automatic documentation with Pydantic POST request and schemaFastAPI Python automatic documentation with Pydantic POST request and schema

También puede "probarlo" y comprobar su punto final de API introduciendo valores para las variables. Aquí, por ejemplo, estamos pasando en “Michael Jordan” para la variable player_name de tipo String.

FastAPI Python automatic documentation with Pydantic POST request and request bodyFastAPI Python automatic documentation with Pydantic POST request and request body

Luego, cuando haga clic en Ejecutar, le dará el cuerpo de la respuesta. No hay necesidad de utilizar una herramienta adicional como Postman.

FastAPI Python automatic documentation with Pydantic POST request and response bodyFastAPI Python automatic documentation with Pydantic POST request and response body

Su documentación interactiva también generará un comando curl para usted, por lo que no tendrá que escribir uno desde cero:

FastAPI Python automatic documentation with Pydantic POST request and CurlFastAPI Python automatic documentation with Pydantic POST request and Curl

Conclusión: Dado que la Documentación Automática viene de fábrica con FastAPI junto con Pydantic y Swagger UI, estas características definitivamente acelerarán tu tiempo de desarrollo. No tienes que instalar ninguna herramienta externa para probar tus peticiones.

Validación de datos

Como nuestro querido amigo Pydantic viene con FastAPI tras la instalación, te dará algunos mensajes de error bastante amistosos cuando tengas problemas con tu código.

FastAPI

from pydantic import BaseModel

from typing import Optional

class Login(BaseModel):
    username: str
    password: str
    agree_to_terms: Optional\[bool]

@app.post("/login")
def login(request: Login):
    if request.username == "janedoe" and   request.password == "password12345":
        return {"message": "Success"}
    return {"message": "Authentication Failed"}

Aquí estamos creando una clase Login que hereda de Pydantic BaseModel con variables de tipo hinted dentro de ella. Primero comprobamos si username es janedoe y password es passworld12345y luego devolvemos un mensaje de éxito o de fallo.

Pasamos a la documentación automática y probamos nuestro cuerpo de petición pasando None al nombre de usuario:

FastAPI Python automatic documentation with Pydantic POST request and change request bodyFastAPI Python automatic documentation with Pydantic POST request and change request body

Pydantic hará su magia, y obtendrás un mensaje amigable diciéndote exactamente cuál es el error. En este caso, devuelve el error Expecting Valueque da en el clavo, ya que hemos introducido None al método username.

FastAPI Python automatic documentation with Pydantic error messageFastAPI Python automatic documentation with Pydantic error message

Conclusión: Flask no tiene ningún soporte interno de validación de datos. Puede utilizar el potente paquete Pydantic para la validación de datos instalándolo con Flask-Pydantic.

Parámetros de URL o ruta

Un parámetro de ruta o URL obtiene un único elemento. Digamos que queremos obtener un solo jugador. Cualquier jugador que tenga un id igual al que introducimos en la URL será devuelto al usuario.

Digamos que tenemos una lista de diccionarios, y queremos obtener un jugador de este archivo JSON:

players = [

    {

        "player_id": 1,
        "name": "Giannis"

    },

    {

        "player_id": 2,
        "name": "Luka"

    }

]

Frasco

@app.get('/players/<int:player_id>')

def get_player_details(player_id):
    for player in players:
        if player["player_id"] == player_id:
            return jsonify(player)

Aquí pasamos nuestra ruta a localhost en el puerto 5000 con un id de 2, y obtenemos de vuelta el jugador con un id de 2.

Flask Python url or path parameters running on localhost returning JSON as response bodyFlask Python url or path parameters running on localhost returning JSON as response body

FastAPI

@app.get("/player/{player_id}")

def get_player_details(player_id: int):
    for player in players:
        if player['player_id'] == player_id:
            return {'player':player['name']}

Aquí pasamos nuestra ruta a localhost en el puerto 8000 con un id de 1, y obtenemos de vuelta el jugador con un id de 1.

FastAPI Python url or path parameters running on localhost returning JSON as response bodyFastAPI Python url or path parameters running on localhost returning JSON as response body

Conclusión: Con FastAPI, ya que utiliza Python type hinting, puedes portar tu código a otros frameworks, como Django. Con Flask, no es portable porque estamos usando type hinting específico del framework, no hinting de Python.

Carpeta de plantillas

La carpeta Templates almacena tus archivos HTML cuando estás construyendo una aplicación web en Flask o FastAPI, y tienes que usar Jinja para mostrar tus variables en HTML. Jinja es un motor de plantillas que te permite escribir código similar a Python para mostrar HTML.

Frasco

Por defecto, Flask busca plantillas en una carpeta "templates". Solo tendrás que crear una en tu estructura de archivos.

Flask Python templates folder in file structure to render HTML filesFlask Python templates folder in file structure to render HTML files

Flask Python templates folder in file structure to render HTML filesFlask Python templates folder in file structure to render HTML files

A continuación, puede utilizar Jinja para mostrar sus variables rodeándolas con llaves dobles:

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Players</title>

</head>

<body>

    <h1>Display Players</h1>

    {{ player.name }}

    {{ player.jersey_number }}

</body>

</html>

Conclusión: Jijnja viene con Flask cuando se instala, lo cual es una gran ventaja. En FastAPI, tienes que instalar Jinja y definir la carpeta de plantillas en tu código.

Servidor de producción

En algún momento querrá desplegar su aplicación y mostrársela al mundo.

Frasco

Flask utiliza un servidor web llamado WSGI, que significa Web Server Gateway Interface y ha sido el estándar de Python durante muchos años. El inconveniente es que es síncrono. Esto significa que si usted tiene un montón de peticiones, tienen que esperar en línea para la cola para completar.

FastAPI

FastAPI utiliza un servidor web llamado ASGI (Asynchronous Server Gateway Interface), que es rapidísimo porque es -bueno, lo has adivinado- asíncrono. Así, si tienes un montón de peticiones entrando, no tienen que esperar a que las otras se completen antes de ser procesadas.

Conclusión: ASGI acelera el rendimiento de las aplicaciones web porque procesa las peticiones de forma asíncrona.

Redoble de tambores, por favor.

El ganador es... bueno, depende.

Así es como puedes elegir.

Utilice Flask si quieres:

  • Un marco probado, ya que existe desde hace mucho tiempo.

  • Desarrollar un prototipo rápido

  • Desarrollar aplicaciones web

Utilice FastAPI si lo desea:

  • Velocidad, en términos de tiempo de desarrollo y rendimiento

  • Para reducir el número de fallos y errores en el código

  • Para crear API desde cero

Vale, ya has visto Flask y FastAPI en acción. Ahora tienes una mejor comprensión de ambos, y te has dado cuenta de cuál sería el más adecuado para tu próximo proyecto.

¿Qué marco eligió? Tweetéanos @VonageDev o @tonyasims.

Compartir:

https://a.storyblok.com/f/270183/400x401/df70d85a84/tonya-sims-1.png
Tonya SimsAntiguos alumnos de Vonage

Tonya es una antigua defensora de los desarrolladores de Python en Vonage.