2022-10-18 02:20 Temps de lecture : 14 min

Top 5 des frameworks Web asynchrones pour Python

La programmation asynchrone est désormais pleinement intégrée à l'écosystème Python. Les développeurs web ont un large éventail de frameworks performants à leur disposition !

Aujourd'hui, le terme "asynchrone" est omniprésent dans la communauté Python. Avec l'introduction de la bibliothèque asyncio dans la version 3.5, Python a pris acte de l'influence de Node.js sur le développement web. Deux nouveaux mots-clés, `async` et `await`, ont été ajoutés au langage. Ce fut un tournant majeur, car le langage Python est habituellement réticent à modifier sa syntaxe de base, sauf en cas de nécessité absolue, ce qui souligne l'importance accordée par les développeurs Python aux capacités asynchrones.

Par conséquent, l'adoption de la programmation asynchrone s'est généralisée. Les bibliothèques, nouvelles et anciennes, ont intégré les coroutines, les frameworks asynchrones ont connu une croissance rapide et de nouveaux sont toujours en cours de développement. Des performances équivalentes ou supérieures à celles de Node.js sont maintenant courantes, et si votre application ne nécessite pas de nombreuses tâches gourmandes en ressources CPU, il est tout à fait possible de traiter plusieurs milliers de requêtes par seconde.

Mais assez de préambule !

Examinons le panorama actuel de Python et explorons certains des meilleurs frameworks asynchrones.

Tornado

Étonnamment, Tornado n'est pas un framework récent. Sa première publication date de 2009 et, depuis lors, il a pour objectif de fournir une programmation asynchrone solide avec une forte simultanéité.

Tornado n'est pas strictement un framework web. Il s'agit d'un ensemble de modules asynchrones, qui servent également à construire le module de framework web. Plus précisément, ces modules comprennent :

  • Coroutines et autres primitives (tornado.gen, tornado.locks, tornado.queues, etc.)
  • Modules de mise en réseau (tornado.ioloop, tornado.iostream, etc.)
  • Serveurs et clients asynchrones (tornado.httpserver, tornado.httpclient, etc.)

Ces modules ont été combinés pour créer les modules de framework finaux : tornado.web, tornado.routing, tornado.template, etc.

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Bonjour, le monde")

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

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

Tornado bénéficie d'une communauté active et engagée au sein de l'écosystème Python, et il est utilisé par des architectes expérimentés pour construire des systèmes haute performance. C'est un framework qui répond depuis longtemps aux problèmes de concurrence, mais son manque de prise en charge du standard WSGI et sa complexité d'utilisation ont freiné son adoption généralisée. (Rappelons que la plupart des bibliothèques Python restent synchrones).

Sanic

Sanic est un framework "moderne" dans le vrai sens du terme. Il ne prend pas en charge les versions Python antérieures à 3.6, il utilise la syntaxe `async`/`await` de manière native et ne nécessite pas une lecture exhaustive de la documentation pour écrire votre premier gestionnaire HTTP.

L'approche de Sanic se traduit par une syntaxe claire et intuitive. Le code ressemble à celui que vous écririez avec n'importe quel autre microframework (comme Flask ou CherryPy), avec juste quelques touches d'asynchrone :

from sanic import Sanic
from sanic.response import json

app = Sanic()

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

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

Sanic est sans doute le framework asynchrone le plus populaire et le plus apprécié dans l'univers Python. Il intègre toutes les fonctionnalités essentielles pour vos projets (routage, middleware, cookies, gestion de versions, plans, vues basées sur des classes, fichiers statiques, streaming, websockets, etc.). Les fonctionnalités manquantes (modèles, support de bases de données, E/S de fichiers, files d'attente) peuvent être ajoutées grâce aux nombreuses bibliothèques asynchrones disponibles.

Vibora

Vibora est un framework proche de Sanic, mais il se concentre sur la performance et vise à devenir le serveur web Python le plus rapide. Dès la première visite de son site web, vous êtes accueilli par un comparatif de performances entre les différents frameworks :

Vibora affirme être plusieurs fois plus rapide que les frameworks classiques et plus de deux fois plus rapide que son concurrent direct, Sanic. Il est important de noter qu'il faut interpréter ces comparaisons avec prudence.

Bien que la syntaxe et les fonctionnalités de Vibora soient comparables à celles de Sanic (voire légèrement supérieures, car il intègre directement des bibliothèques populaires et des fonctionnalités telles que les modèles), Sanic est considéré comme plus mature en raison de sa plus grande ancienneté et de sa communauté plus importante.

from vibora import Vibora, JsonResponse

app = Vibora()

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

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

Si vous accordez une grande importance à la performance, Vibora pourrait être le framework idéal. Cependant, au moment de la rédaction de cet article, Vibora est en cours de réécriture pour devenir encore plus rapide, et le lien vers sa section dédiée à la performance indique qu'il est en "développement intensif". Cette situation risque de décevoir ceux qui ont adopté Vibora plus tôt et qui pourraient devoir faire face à des changements importants. Cependant, le monde asynchrone de Python est encore récent et personne ne s'attend à une stabilité totale.

Quart

Si vous appréciez le développement avec Flask mais que vous regrettez son manque de support asynchrone, vous apprécierez grandement Quart.

Quart est conforme à la norme ASGI, qui remplace le célèbre standard WSGI et offre un support asynchrone. L'intérêt de Quart est qu'il n'est pas simplement similaire à Flask, mais qu'il respecte également l'API Flask ! L'auteur de ce framework souhaitait conserver l'expérience utilisateur de Flask tout en y ajoutant le support asynchrone, les websockets et HTTP 2. Par conséquent, vous pouvez apprendre Quart directement à partir de la documentation de Flask, en gardant à l'esprit que les fonctions de Quart sont asynchrones.

from quart import Quart

app = Quart(__name__)

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

app.run()

Ressemble (presque) exactement à Flask, n'est-ce pas ? !

Étant donné que Quart est une évolution de Flask, toutes les fonctionnalités de Flask sont disponibles : routage, middleware, sessions, modèles, plans, etc. Vous pouvez même utiliser les extensions Flask directement dans Quart. Cependant, Quart ne prend en charge que Python 3.7+, ce qui, si vous n'utilisez pas la dernière version de Python, pourrait signifier que l'asynchrone n'est pas la bonne voie. 🙂

La documentation est un peu légère si vous n'avez pas d'expérience préalable avec Flask, mais je peux recommander Quart car c'est probablement le seul framework asynchrone proche de sa version 1.0.

FastAPI

Le dernier framework de cette liste (mais non le moindre) est FastAPI. Contrairement à ce que son nom pourrait suggérer, il ne s'agit pas d'un framework uniquement dédié aux API. En réalité, FastAPI semble être le framework le plus riche en fonctionnalités et en documentation que j'ai rencontré lors de mes recherches sur les frameworks asynchrones Python.

L'auteur de FastAPI a étudié en profondeur plusieurs autres frameworks, des plus anciens comme Django aux plus modernes comme Sanic, ainsi que des technologies comme NestJS (un framework web Node.js en Typescript). Leur philosophie de développement et leurs analyses comparatives détaillées peuvent être consultées ici.

La syntaxe est particulièrement agréable ; on peut même affirmer qu'elle est bien plus élégante que celle des autres frameworks que nous avons examinés :

from fastapi import FastAPI

app = FastAPI()

@app.get("/utilisateurs/me")
async def lire_utilisateur_courant():
    return {"utilisateur_id": "l'utilisateur actuel"}

@app.get("/utilisateurs/{utilisateur_id}")
async def lire_utilisateur(utilisateur_id: str):
    return {"utilisateur_id": utilisateur_id}

Voici maintenant la liste des fonctionnalités phares qui font de FastAPI un framework exceptionnel :

Génération automatique de la documentation de l'API : dès que vous avez créé vos points d'accès, vous pouvez interagir avec l'API via une interface utilisateur conforme aux normes. SwaggerUI, ReDoc et d'autres sont pris en charge.

Le framework génère également automatiquement la documentation du modèle de données en utilisant JSON Schema.

Développement moderne : Le terme "moderne" est souvent employé à tort et à travers, mais FastAPI justifie pleinement cette appellation. L'injection de dépendance et l'indication de type sont des éléments centraux, ce qui permet non seulement d'appliquer de bonnes pratiques de codage, mais aussi d'éviter les erreurs et les confusions à long terme.

Documentation complète : Personnellement, je suis un grand amateur de documentation de qualité. Et sur ce point, FastAPI excelle. Sa documentation contient des centaines de pages qui expliquent presque toutes les petites subtilités et les "pièges" potentiels pour les développeurs de tous niveaux. On ressent un réel "cœur et une âme" dans la documentation, et la seule comparaison possible est celle de Django (oui, la documentation de FastAPI est à ce point excellente !).

Au-delà des bases : FastAPI prend en charge les WebSockets, le streaming, ainsi que GraphQL, en plus de proposer tous les outils traditionnels tels que CORS, les sessions, les cookies, etc.

Qu'en est-il des performances ? Eh bien, FastAPI est basé sur l'excellente bibliothèque Starlette, ce qui lui confère des performances comparables à celles de Node.js, voire même à Go dans certains cas ! Dans l'ensemble, j'ai l'impression que FastAPI a le potentiel de devenir le meilleur framework asynchrone pour Python.

Conclusion

Le paysage asynchrone de Python est en pleine effervescence. De nouveaux frameworks apparaissent, les anciens sont réécrits et les bibliothèques évoluent pour s'adapter au comportement asynchrone. Bien que Python intègre le support d'une boucle d'événements, et qu'il soit possible de rendre certaines parties de votre application asynchrones, vous pouvez choisir de miser sur un des frameworks mentionnés dans cet article. N'oubliez pas de prendre en compte les enjeux à long terme : plusieurs frameworks asynchrones Python en sont à leurs débuts et évoluent rapidement, ce qui risque de complexifier votre processus de développement et d'augmenter les coûts. La prudence est donc de mise !

Cependant, tout compte fait, Python est désormais prêt à fournir des performances optimisées en matière de frameworks web. Si vous envisagiez de migrer vers Node.js, ce n'est plus une nécessité ! 🙂

Cela vous intéresse ? Maîtrisez Python dès aujourd'hui !

Auteur
France

Rédacteur tech, guides pratiques et astuces numériques.