Il y a depuis longtemps deux frameworks web bien implantés dans le monde Python : Django et Flask. Il y a des pros et des cons à chacun de ces frameworks, Django étant souvent présenté comme plus complet mais plus difficile à prendre en main, Flask comme étant plus simple pour déployer rapidement une API.
Depuis quelques mois, on entend de plus en plus parler d'un nouveau framework: FastAPI. Par exemple, JetBrains conduit tous les ans une enquête auprès de développeur.se.s Python et FastAPI a fait une entrée remarquée en 2020 :
FastAPI was introduced to the options for the first time with this iteration of the survey, and it appears to be the third most popular web framework for Python.
Ce framework se veut moderne, rapide, prêt au déploiement. Voyons voir ça !
Installation
L'installation se fait bien évidemment avec pip
:
pip install fastapi[all]
Petit truc exotique quand même : des crochets dans le nom du paquet. Histoire de mettre un peu de paillettes dans la vie des développeurs.
Notez qu'uvicorn
sera installé en même temps. Il nous servira de serveur pour nos exemples.
hello, world
Dans un dossier myapi
, on crée un fichier main.py
:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "hello, world"}
Ce code est très simple à comprendre. On crée une instance de FastAPI
nommée app
, puis on ajoute une route vers la racine avec une opération GET, grâce une élégante syntaxe à base d'annotations.
On lance un serveur pour exposer notre API :
$> cd myapi
$> uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [1972] using watchgod
INFO: Started server process [16100]
INFO: Waiting for application startup.
INFO: Application startup complete.
On utilise ici uvicorn
comme serveur. On lui demande d'utiliser le module Python main
(il faut donc exécuter la commande depuis le dossier où se trouve notre fichier main.py
) et y chercher l'instance app
de FastAPI.
On ouvre l'adresse indiquée dans un navigateur :
L'option --reload
demande à uvicorn
de recharger le site au fur et à mesure que le fichier main.py
est modifié, sans avoir besoin de redémarrer l'application.
Pour tester cette fonctionnalité, on ajoute une nouvelle route /about
dans à notre API :
@app.get('/about')
async def about():
return {"about": "This is my first api with FastAPI"}
Les logs de uvicorn
montrent que les changements sont bien détectés et chargés :
WARNING: WatchGodReload detected file change in '['C:\\myapi\\main.py']'. Reloading...
INFO: Started server process [3708]
INFO: Waiting for application startup.
INFO: Application startup complete.
Cette nouvelle route est accessible par notre navigateur :
Route avec paramètres
Il est bien sûr possible d'ajouter des paramètres à une route.
Pour l'exemple, on crée une variable users
avec la liste des utilisateurs. On ajoute une route de type GET pour récupérer cette liste, et une route de type POST pour ajouter un élément à cette liste :
users = ['pierre', 'natacha', 'benjamin']
@app.get('/users/list')
async def users_list():
"""Get the list of available users."""
return json.dumps(users)
@app.post('/users/add/{name}')
async def users_add(name: str):
"""Add a new user.
:param name: the name of the new user
"""
users.append(name)
return {'added': name}
On utilise curl
pour tester nos nouvelles routes :
$ curl --request GET http://127.0.0.1:8000/users/list
"[\"pierre\", \"natacha\", \"benjamin\"]"
$ curl --request POST http://127.0.0.1:8000/users/add/florian
{"added":"florian"}
$ curl --request POST http://127.0.0.1:8000/users/add/denis
{"added":"denis"}
$ curl --request POST http://127.0.0.1:8000/users/add/bertrand
{"added":"bertrand"}
$ curl --request GET http://127.0.0.1:8000/users/list
"[\"pierre\", \"natacha\", \"benjamin\", \"florian\", \"denis\", \"bertrand\"]"
Documentation de l'API
FastAPI se charge de générer la documentation de l'API. Cette documentation est accessible grâce à des routes ajoutées automatiquement à l'API.
Pour cela, il génère un schéma OpenAPI, en récupérant les docstrings des fonctions annotées. Ce schéma est disponible avec la route /openapi.json
:
Ensuite, il utilise Swagger UI et Redoc pour le rendu. Ces 2 versions de la documentation sont accessibles avec les routes /docs
et /redoc
respectivement.
On a ainsi la liste des routes, avec leurs types, leurs paramètres, leurs documentations. On peut tester notre API directement depuis ces pages. Et comme tout est en auto-reload, on peut faire nos modifications au fur et à mesure et uvicorn
remettra à jour /docs
et /redoc
pour qu'on puisse retester immédiatement.
Conclusion
Mes premières impressions sur FastAPI sont très positives. La syntaxe est proche de celle de Flask, peut-être encore plus simple et élégante. La génération automatique et out-of-the-box de la documentation est vraiment cool ! Je ne me suis pas intéressé à l'aspect performances du framework, pour me concentrer sur son utilisation. Je vous laisse consulter la section "Benchmarks" du site officiel pour cela.