Рубрики
Без рубрики

Python Fastapi: ¿El Mejor Framework de Python?

Estos últimos días he estado percando una librería para python que se está volviendo muy populity, fas … Tagged python, Spanish, WebDev, Tulciory.

Estos últimos días he estado percando una librería para python que se está volviendo muy popular, fastapi, un framework para crear apis. Fastapi Artete Ayudarnos A Apis apis rápidas de manera sencilla y con muy Poco Código y Con un rendimiento extrorinario, para soportar una alta carga de peticiones web.

Фаскапи против Джанго против Флэзы против пирамиды

FASTAPI QUEDA EN PRIMER LUGAR EN RESPUESTAS POR SEGUNDO FRENTE A FRAMEWORKS Más Populares Como Django, Pyramid O Flask. Y también queda en los primeros lugares si lo comparatamos con frameworks de otros lenguajes de programación, como php o javascript.

Mira Estas Comparaciones que usan información de Techempower Анкет Он рестабтадо En Azul Los Frameworks de Python. El Número Indica La Cantidad de Respuestas Por Segundo, Mientras Más Alto Mejor.

Número de respuestas por segundo para peticiones que devuelven una fila de la base de datos. Información Tomada de https://www.techempower.com/benchmarks

Número de respuestas por segundo para peticiones Que devuelven veante filas de la base de datos. Información Tomada de https://www.techempower.com/benchmarks

Tipado y asincrónismo en python

FASTAPI ES TOTLIMENTE COMPATIBLE CON EL TIPADO Y EL ASINCRónismo de Las últimas версии de Python.

Con La Intención de Mantener Este Tuperial LO Más Sencillo Postible voy asarlas únicamente donde sea necesario , si no es Estrictamente necesario incluirlas voy is olmitirs. Menciono Lo Передняя пара Que Tomes en Cuenta Que Cada Fragmento de Código Donde Se Используйте Fastapi Puede Incorporar Asincronismo y Tipado, Según рассматривает Necesario.

¿Cómo instalar fastapi?

Para instalarlo Vamos Care un entorno Virtual Con Pipenv. Además de fastapi necesitaremos uvicorn; ООН Servidor Asgi, El Cual Usaremos para servir nuestra api.

Si no sabes usar pipenv date una vuelta por Ла Entrada Donde откровенно Como usar esta erramienta de manejo de enterornos virtuales.

pipenv install fastapi uvicorn

ActiveMos el Entorno Virtual Para Tener Acceso A Los Paquetes Que acabamos de entalar.

pipenv shell

Continuación Vamos A Crear Un Archivo Llamado main.py , Aquí estará Todo el Código Que usaremos para crear nuestra api.

touch main.py

Y ahora vamos a colocar el código mínimo para tener un servidor.

# main.py
from fastapi import FastAPI

app = FastAPI()

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

LO Primero Será Importar La Librería, Después Crearemos una instancia de Fastapi. Continuación escribiremos una función que devuelva un diccionario y usaremos un decorador con la ruta que queremos que capture nuestra aplicación. Эс Тодо.

Uvicorn se encargará de servir la api que acabamos de crear por medio del siguiente comando:

uvicorn main:app --reload

Analicemos brevemente lo que acabamos de ejecutar:

  • Главный SE Refiere Al Nombre de Nuestro Archivo
  • приложение Es La Instancia de Fastapi Que Creamos
  • -переоценивать Le Dice A Uvicorn Que Escuche Cambios en el Código
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

Como Puedes Ver, Si Todo Salió Bien, Tendremos un Servidor Corriendo Localhost: 8000

curl localhost:8000
--{"Hello":"World"}

Y, si Realizamos una petición al puerto 8000, gatendremos nuestra resuesta en formato json, sin necesidad de haberla convertido desde el diccionario python.

Capturando Parámetros

Ahora Pasemos de Rutas Estáticas A Rutas Con Parámetros.

Para capturar parámetros agregaremos estas lineas al archivo main.py Que ya tenemos. Impormamos el Tipado Необязательно против La Intención de Capturar Nuestros Parámetros Opcionales. Para Este ejemplo voy usar el tipado que of recen las nuevas версии de python, nota como fijamos item_id : инт Para Que acepte únicamente Valores de Tipo Entero.

from fastapi import FastAPI
from typing import Optional

app = FastAPI()

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

@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
    # otra_funcion_para_item_id(item_id)
    # otra_function_para_q(q)
    return {"item_id": item_id, "q": q}

DENTO DEL DECERADOR COLOCAMOS ENTRE CORCHETES EL NOMBRE DE LA переменная QUEEMOS CAPLURAR. Esta variable se la pasaremos como parámetro a nuestra función

Como Segundo parámetro, opcional, esperaremos un parámetro get, de nombre “q”.

En Este Caso, lo único Que hará nuestra función es Devolver Ambos Valors en formato Json. Aunque, Seguramente ya te diste cuenta cuenta de Que, en lugar de sommonemente devolverlos, puedes usar esos datos para buscar en una base de datos, ingresar esa información como parámetros otra función y retornar otra otra cosa tallmenta distinta distinta distinta distinta distinta distinta distinta distinta.

curl localhost:8000/items/42
--{"item_id":42,"q":null}

Como no Offificamos un parámetro Получите Opcional nos devuelve un NULL en su lugar. Mira Lo Que Scede Si Intentamos Enviar un Valor Inválido, Es decir, Que no Sea Un Entero.

curl localhost:8000/items/texto -i
--HTTP/1.1 422 Unprocessable Entity
--date: Sun, 11 Oct 2020 00:13:38 GMT
--server: uvicorn
--content-length: 104
--content-type: application/json
--
--{"detail":[{"loc":["path","item_id"],"msg":"value is not a valid integer","type":"type_error.integer"}]}

FASTAPI SE ENCARGA DE HACERNOS SABER QUE EL VALOR ENVIADO ES INVALIDO MEDIANTE UNA RESPUEESTA http 422. Ahora hagamos una petición que incluya valores reformos para ambos parámetros de nuestra funcion read_item ()

curl localhost:8000/items/42?q=larespuesta
--{"item_id":42,"q":"larespuesta"}

Assema como nos regresa el número que le le pasemos, морское море, аси como nuestro parámetro Get Opcional llamado “q”.

ОТДЫХАТЬ

Fastapi se encarga de manejar los métodos http de manera bastante intuitiva, smaptiemede cambiando la función de nuestro decorador por sustivo método de petición http

@app.get()
@app.post()
@app.put()
@app.delete()

Además ES POSIBLE OPFIFICICAR UN Código de Respuesta Opcional Como Parámetro en Cada Una de estas Rutas.

@app.post(status_code=201)

Para Corroborarlo Creemos Otra función, Esta en Lugar de Usar El Decorador @app.get , usará @app.post Y Devolverá un Código 201.

from fastapi import FastAPI
from typing import Optional

app = FastAPI()

# {...código anterior}

@app.post("/items/", status_code=201)
def post_item():
    return {"item": "our_item"}

Este Decorador Capturará Cualquier Petición Post a la url /Предметы/ . Mira lo Que Scede Si Intentamos hacer una petición get, en lugar de una post.

curl localhost:8000/items/ -i
--HTTP/1.1 405 Method Not Allowed
--date: Sun, 11 Oct 2020 00:56:06 GMT
--server: uvicorn
--content-length: 31
--content-type: application/json
--
--{"detail":"Method Not Allowed"}

Asing, Cualquier Otro método no Soportado recibirá una respuesta 405 (Método no ourmitido). Ахора Хагамос la petición raffa, con post.

curl -X POST localhost:8000/items/
--HTTP/1.1 201 Created
--date: Sun, 11 Oct 2020 00:57:05 GMT
--server: uvicorn
--content-length: 19
--content-type: application/json
--
--{"item":"our_item"}

Stusta Que recibimos un código 201 como respuesta, así como nuestra respuesta en formato json.

Печенье

Лектура де печенья

Si Queremos Leer Cookies USANDO FASTAPI TENDREMOS QUE IMIPORMAR COOKIE Y LUEGO DENIUR UN PARámetro, QUE SERU UNA ENTACIA DE ESA COOKIE. Si todo sale bien podremos mandar una cookie y fastapi nos ugresará su Valor.

from fastapi import Cookie, FastAPI
from typing import Optional

app = FastAPI()

# {...código anterior}

@app.get("/cookie/")
def read_cookie(my_cookie = Cookie(None)):
    return {"my_cookie": my_cookie}

Si Mandamos una cookie Usando curl.

curl --cookie "my_cookie=home_made" localhost:8000/cookie/ -i
--{"my_cookie":"home_made"}

Колокарное печенье

Para Colocar Cookie escesario Acceder al objeto de respuesta de nuestra petición http, y además necesitamos ely tipado de este parámetro. Por ward recuerda impormarlo

from fastapi import Cookie, FastAPI, Response
from typing import Optional

app = FastAPI()

# {...código anterior}

@app.get("/setcookie/")
def set_cookie(response: Response):
    response.set_cookie(key="myCookie",
                        value="myValue")
    return {"message": "The delicious cookie has been set"}

Mira la cabecera Set-Cookie que aparece en nuestra respuesta. La ponsencia de esta cabecera http o Header indica que hemos recibido la instrución de colocar nuestra cookie reforramente.

curl localhost:8000/setcookie/ -i
--HTTP/1.1 200 OK
--date: Mon, 19 Oct 2020 20:45:08 GMT
--server: uvicorn
--content-length: 31
--content-type: application/json
--set-cookie: myCookie=myValue; Path=/; SameSite=lax
--
--{"message":"Delicious cookies"}

Заголовки o cabeceras http

Заголовки Leer o Cabeceras http

Para Leer cabeceras http se hará de la misma manera que con las cookies. POR WARD Recuerda ИМПИМАМИНГ.

from fastapi import Cookie, Header, Response, FastAPI
from typing import Optional

app = FastAPI()

# {...código anterior}

@app.get("/headers/")
def return_header(user_agent = Header(None)):
    return {"User-Agent": user_agent}

Listo, ahora tendremos una cabecera que nos devolverá el el agent фактические, Con que estamos realizando la petición, el cual manda Automáticamente curl Con Cada Petición, Por lo que deberiamos ser seraces de capturarlo.

curl localhost:8000/headers/ -i
--HTTP/1.1 200 OK
--date: Mon, 19 Oct 2020 19:33:45 GMT
--server: uvicorn
--content-length: 28
--content-type: application/json
--
--{"User-Agent":"curl/7.52.1"}

En Este Caso, Como Hicimos La Petición Con Curl, nos retornará la cadena de texto “curl/nuestra_versión”. Си Хицирамос la petición con un navegador web gopendriamos el Valor de пользовательский парашют Навегадор.

Colocar Headers o Cabeceras http

Para Colocar заголовки Necesitamos acceder al objeto ответ, Este objeto tiene una propiedad lmamada заголовки Al Que Podemos Agregarle Valores Como si fuera un diccionario.

from fastapi import Cookie, Header, Response, FastAPI
from typing import Optional

app = FastAPI()

# {...código anterior}

@app.get("/setheader/")
def set_header(response: Response):
    response.headers["response_header"] = "my_header"
    return {"message": "header set"}

Ahora hacemos una petición a la url que acabamos de crear. Esperamos que la respuesta contenga un hage o cabecera http llamada response_header

curl localhost:8000/setheader/ -i
--HTTP/1.1 200 OK
--date: Sat, 24 Oct 2020 16:11:31 GMT
--server: uvicorn
--content-length: 24
--content-type: application/json
--response_header: my_header
--x-my_data: X-my_data
--
--{"message":"header set"}

Промежуточное программное обеспечение

Sí, Aunque Fastapi es Bastante Simple También Incorpora la funcionalidad de usar промежуточный программный обеспечение Como parte de su ciclo de petición-respuesta.

¿Нет сабсов rek es on undware? De Manera Simplista, ООН промежуточный программное обеспечение ES una Pieza de Código Que Colocas antes de la Petición, para “receptarla” y hacer (o no) algo conella. ООН промежуточное программное обеспечение Funciona de Manera аналогично Asas carreras de donde la petición y la respuesta serían las estafetas que van pasándose de un Промежуточное программное обеспечение Al Otro, промежуточное программное обеспечение Cada Puede Modificar La Petición O La Respuesta O Dejarla Intacta Para Pasarla Al Siguiente Промежуточное программное обеспечение.

Esquema super simplificado de un Middleware El Contexto Web

Para USAR промежуточное программное обеспечение Basta Con Colocar UN Decorador @app.middleware (‘http’) sobre una función. Esta función Recibe el objeto de la petición web (запрос) y una función llamada call_next, que recibirá la petición web y retornará una resuesta.

from fastapi import Cookie, Header, Response, FastAPI
from typing import Optional

app = FastAPI()

@app.middleware("http")
async def add_something_to_response_headers(request, call_next):
    response = await call_next(request)
    # Ahora ya tenemos la respuesta que podemos modificar o procesar como querramos
    response.headers["X-my_data"] = "x-my_data"
    return response

La respuesta a nuestra petición la obtenemos después de llamar a call_next Pasándole Como Parámetro el objeto запрос , por lo que todas las indificaciones a la petición van antes de la llamada a call_next , mientras Que todas las indificaciones a la respuesta van despúes de call_next

from fastapi import Cookie, Header, Response, FastAPI
from typing import Optional

app = FastAPI()

# {...código anterior}

@app.middleware("http")
async def my_middleware(request, call_next):
    # modificaciones a REQUEST
    response = await call_next(request)
    # modificaciones a RESPONSE
    return response

Ahora Hagamos un Curl A Localhost: 8000 Para Ver Si Funcionó. Mira Como Ahora Tenemos Un Header O Cabecera http en la respuesta, y este a a la información que le acabamos de colocar.

curl localhost:8000 -i
--HTTP/1.1 200 OK
--date: Mon, 19 Oct 2020 19:20:35 GMT
--server: uvicorn
--content-length: 17
--content-type: application/json
--x-my_data: X-my_data
--
--{"Hello":"World"}

Mientras El Middleware Que Creamos Siga Activo, Cada Nueva Resuesta Que obtengamos Contendrá Ese Header y Sucolidy Valor.

Промежуточное программное обеспечение включено

FASTAPI VIENE CON UNA SERIE DE MIDELWARE включаю в себя QUE PODEMOS USAR Y AGREGAR A LA LISTA DE MIDENTWARES POR LOS QUE PASARán Nuestras Peticiones. PARA AGREGAR UN MIDELWARE BASTA CON USAR EL Método add_middleware () , De Nuestra App.

Нет es esesario que agregues el siguiente código. Es solo para que conozcas algunas de las opciones, включая Fastapi como parte de su código.

from fastapi import Cookie, Header, Response, FastAPI
from typing import Optional

from fastapi.middleware.gzip import GZipMiddleware
# from fastapi.middleware.trustedhost import TrustedHostMiddleware
# from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware

app = FastAPI()

app.add_middleware(GZipMiddleware, minimum_size=1000)
  • Gzipmiddleware: SE Encarga de USAR Compresión Gzip en tus respuestas
  • Trusthostmiddleware: Conste Middleware Podemos DUSIRLE A FASTAPI CAULES SON LOS DOMINIOS SEGUROS, аналогичная переменная A LA
  • Httpsredirectmiddleware: se encarga de redirigir las peticiones http a su версия en https

Манехо де Формуляриос

Lo primero que tenemos que hacer para manejar formularios es instalar la degyencia Python-Multipart Nuestro Entorno Virtual. Puedes Usar Pip O Pipenv, yo Usaré pipenv.

Asegúrate de Estar Dentro del Entorno Virtual El Cual Estás Trabajando.

pipenv install python-multipart

Una Vez Instalado Nuestro Paquete, Crearemos una función que reciba un parámetro igual al objeto Форма . Recuerda, Nuevamente, Importar Форма desde FASTAPI

También toma en cuenta que si quieres agregar más campos basta con sesvicer más parámetros para la función.

Sí, Puede Sonar Bastante oversio pero es mejor mencionarlo.

from fastapi import Cookie, Header, Response, FastAPI, Form
from typing import Optional

app = FastAPI()

# {...código anterior}

@app.post("/subscribe/")
async def subscribe(email=Form(...)):
    return {"email": email}

Ahora intentemos mandar un dato usando un formulario usando curl.

curl -X POST -F 'email=email@example.org' localhost:8000/subscribe/
--{"email":"email@example.org"}

Veremos como nos urgesa un objeto json, con el correo que mandamos en el formulario, como respuesta.

Манехо де архивос

De la misma manera que para los formularios, el manejo de archivos requiere la librería Python-Multipart Анкет Instalalá USANDO PIP O PIPENV SI Aún NO LO имеет Hecho. Una Vez Hecho Esto Agrega Файл y Uploadfile LAS Importaciones.

POR ОТВЕТСТВЕННЫЙ ВОСПОЛНИТЕЛЬНЫЙ ПЕРЕСМОТРЕЙТЕ НЕМЕСАРИО УСАР ЭЛ ТИПАДО -де -Питон Пара -Эсте Эйпенто, не очень

from fastapi import Cookie, Header, Response, FastAPI, Form, File, UploadFile
from typing import Optional

app = FastAPI()

# {...código anterior}

@app.post("/files/")
async def create_file(file: bytes = File(...)):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    return {"filename": file.filename}

Para Este Ejemplo Vamos A Crear Un Archivo Sencillo de Texto.

El Siguiente Comando Creará Un Archivo de extensión txt en nuestra carpeta фактически. Сияние No Te Sientes Cómodo USANDO LA TERMINAL DE GNU/LINUX VISTA Mi Serie de Entradas Donde Explico Los Comandos Básicos.

printf "texto" > archivo.txt

Наблюдение Комо Уна Петичион А /файлы/ NOS Devuelve El Tamaño de Nuestro Archivo.

curl -F "file=@archivo.txt" localhost:8000/files/
--{"file_size":5}

Mientras que una petición a /загрузить файл/ nos devuelve el nombre de nuestro archivo

curl -F "file=@archivo.txt" localhost:8000/uploadfile/
--{"filename":"archivo.txt"}

Seguramente ya habrás nutado Que en ningún caso el archivo está siendo Guardado, Sino Que Solo Se Pone A Disposición de Fastapi , Para Que Hagamos con él lo que queramos dentro de nuestra función.

Манехо -де -ошибка

Fastapi Cuenta con una serie de excepciones que podemos usar para manejar los errores de nuestra aplicación.

Para Este ejemplo nuestra función solo retornará un un, pero bien podrías colocar esta excepción en la búsqueda fallida de o objeto en la base de datos o alguna otra situación que se ocurra.

from fastapi import Cookie, Header, Response, FastAPI, Form, File, UploadFile, HTTPException
from typing import Optional

app = FastAPI()

# {...código anterior}

@app.get("/error/")
def generate_error():
    raise HTTPException(status_code=404, detail="Something was not found")

Elegimos el Código A Devolver Con status_code y La Información Adicional Con деталь Анкет

Si Hacemos una Petición Web A /ошибка/ recibiremos una respuesta http 404, junto con la respuesta

curl localhost:8000/error/ -i
--HTTP/1.1 404 Not Found
--date: Mon, 19 Oct 2020 20:21:28 GMT
--server: uvicorn
--content-length: 36
--content-type: application/json
--x-my_data: X-my_data
--
--{"detail":"Something was not found"}

Si Lo Deseamos También Podemos Agregar Cabeceras http o Заголовки A La Respuesta Deciertamente Como un Armeryo Llamado Headers En nuestra Excepción.

from fastapi import Cookie, Header, Response, FastAPI, Form, File, UploadFile, HTTPException
from typing import Optional

app = FastAPI()

# {...código anterior}

@app.get("/error/")
def generate_error():
    raise HTTPException(status_code=404,
                        detail="Something was not found",
                        headers={"X-Error": "Header Error"},)

Тестирование en fastapi

FASTAPI CONTIENE UN CLIENTE CON EL QUE PODEMOS HACER TESTEO. Antes de Empezar realizar el testing vamos instalar los paquetes necesarios para hacerlo: pytest y запросы.

Si Quieres profundizar en el testeo en python tengo Una Entrada Donde Expongo Algunas de Las Librerías Pricinales Para Hacer Testing.

pipenv install requests pytest

Ahora que ya los tenemos vamos a crear un archivo de testeo llamado test_api.py y un archivo _ _init__.py Para Que Python Poder Tener Acceso A Nuestros Módulos.

touch __init__.py test_apy.py

En nuestro archivo test_api.py Вамос Колокар Эль -Сигюенте Кодиго.

from fastapi.testclient import TestClient
from typing import Optional

from .main import app

client = TestClient(app)

def test_read_main():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"Hello": "World"}

Como Puedes Apreciar en el Código передний день:

  • client.get () se encarga de Realizar la petición root
  • response.status_code Contiene el Código de Respuesta
  • response.json () nos devuelve el cuerpo de la respuesta en formato json

Si corremos pytest veremos que se ejecutan los tests cropersientes para recorar que cada uno de los elementos перед настройками моря Igual Al Valor Esperando.

pytest
--======== test session starts ===========
--platform linux -- Python 3.7.2, pytest-6.1.1, py-1.9.0, pluggy-0.13.1
--rootdir: /home/usuario/fastAPI
--collected 1 item
--test_api.py .  [100%]
--
--======== 1 passed in 0.17s =============

DocumentAción en fastapi

Хаста Эсте он ocultado una de las características más geniales de fastapi , нет, я не могу. Asи, я сабл, Que que me refiero: ¡Documentación Automática!

Sí, Como Seguramente Ya Sabías, Fastapi Cuenta Con DocumentAción Automática USANDO чванство y Redoc , нет Tienes Que Agregar Código, Ni Specilecer una переменная para esto, sencillamente abre tu navegador y dirígete a tu Localhost: 8000/docs/ y Localhost: 8000/redoc/ , Соответствующий, Y Verás La DocumentAción Interactiva Generada Automáticamente.

Развертывание грехов Docker

El Despliegue También Es Una Tarea Sencilla de Realizar.

Para Hacer развертывание грех USAR Docker Basta Con Correr Uvicorn, Юсто Комо Хицимос Аль Принцио Де -Эсте.

uvicorn main:app --host 0.0.0.0 --port 80

Развертывание Con Docker

Hacer Unparation Con Docker Es Super Sencillo, El Creador de Fastapi Ya nos provee de una Imagen de docker personalizada que podemos usar como base para nuestro dockerfile. Primero Creemos Un Archivo Dockerfile.

touch Dockerfile

Ahora vamos a colocar lo siguiente dentro:

FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7

COPY . /app

Le Indicamos A Docker Que Copie todo el Contenido de Nuestra Carpeta Actual en la Carpeta /приложение . Despues de la instucción Копия Puedes Agregar Más Código para para perervicizar tu Imagen.

Continuación vamos, компонентный La Imagen.

docker build -t fastapi .

Cuando termine de Compilling nuestra Imagen vamos uncer uncendor en segundo plano, en el puerto 80. Este Compenedor USA Обилизованный пара Пара Сервир Эльнидо.

docker run -d --name fastapicontainer -p 80:80 fastapi

La Configuración de Uvicorn y el USO de Sertiados SSL, Ya Sea USAR Cerbot o Traefik o alguna otra opción ya зависит от де.

Conso Esto Consulye Mi Pequeño Учебное пособие Fastapi. Esta fue únicamente una pequeña inventución con las opciones que yo grisho más artantes, por ward Lee La DocumentAción Oficial para profundizar en cada una de las opciones que fastapi tiene dishonibles.

Te Gustaría Leer más Contenido Como Este?

HAZ Click Aquí

Оригинал: “https://dev.to/silicosis/python-fastapi-como-django-pero-mas-rapido-tutorial-2laj”