Français

Explorez Tornado, le framework web Python asynchrone. Créez des applications évolutives et performantes avec nos explications, exemples et bonnes pratiques.

Documentation Tornado : Un Guide Complet pour les Développeurs du Monde Entier

Tornado est un framework web Python et une bibliothèque de réseau asynchrone, initialement développé chez FriendFeed. Il est particulièrement adapté au long-polling, aux WebSockets et à d'autres applications qui nécessitent une connexion de longue durée avec chaque utilisateur. Ses E/S réseau non bloquantes le rendent extrêmement évolutif et un choix puissant pour créer des applications web haute performance. Ce guide complet vous présentera les concepts fondamentaux de Tornado et fournira des exemples pratiques pour vous aider à démarrer.

Qu'est-ce que Tornado ?

Au cœur de sa conception, Tornado est un framework web et une bibliothèque de réseau asynchrone. Contrairement aux frameworks web synchrones traditionnels, Tornado utilise une architecture mono-thread basée sur une boucle d'événements. Cela signifie qu'il peut gérer de nombreuses connexions simultanées sans nécessiter un thread par connexion, ce qui le rend plus efficace et évolutif.

Caractéristiques Clés de Tornado :

Configurer Votre Environnement Tornado

Avant de plonger dans le développement avec Tornado, vous devez configurer votre environnement. Voici un guide étape par étape :

  1. Installer Python : Assurez-vous d'avoir Python 3.6 ou une version ultérieure d'installé. Vous pouvez le télécharger depuis le site officiel de Python (python.org).
  2. Créer un Environnement Virtuel (Recommandé) : Utilisez venv ou virtualenv pour créer un environnement isolé pour votre projet :
    python3 -m venv myenv
    source myenv/bin/activate  # Sur Linux/macOS
    myenv\Scripts\activate  # Sur Windows
  3. Installer Tornado : Installez Tornado en utilisant pip :
    pip install tornado

Votre Première Application Tornado

Créons une simple application "Hello, World!" avec Tornado. Créez un fichier nommé app.py et ajoutez le code suivant :

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()

Maintenant, exécutez l'application depuis votre terminal :

python app.py

Ouvrez votre navigateur web et naviguez vers http://localhost:8888. Vous devriez voir le message "Hello, World!".

Explication :

Gestionnaires de Requêtes et Routage

Les gestionnaires de requêtes sont le fondement des applications web Tornado. Ils définissent comment traiter les requêtes HTTP entrantes en fonction de l'URL. Le routage associe les URL à des gestionnaires de requêtes spécifiques.

Définir les Gestionnaires de Requêtes :

Pour créer un gestionnaire de requêtes, héritez de la classe tornado.web.RequestHandler et implémentez les méthodes HTTP appropriées (get, post, put, delete, etc.).

class MyHandler(tornado.web.RequestHandler):
 def get(self):
  self.write("Ceci est une requête GET.")

 def post(self):
  data = self.request.body.decode('utf-8')
  self.write(f"Données POST reçues : {data}")

Routage :

Le routage est configuré lors de la création de l'objet tornado.web.Application. Vous fournissez une liste de tuples, où chaque tuple contient un modèle d'URL et le gestionnaire de requêtes correspondant.

app = tornado.web.Application([
 (r"/", MainHandler),
 (r"/myhandler", MyHandler),
])

Modèles d'URL :

Les modèles d'URL sont des expressions régulières. Vous pouvez utiliser des groupes d'expressions régulières pour capturer des parties de l'URL et les passer comme arguments aux méthodes du gestionnaire de requêtes.

class UserHandler(tornado.web.RequestHandler):
 def get(self, user_id):
  self.write(f"ID Utilisateur : {user_id}")

app = tornado.web.Application([
 (r"/user/([0-9]+)", UserHandler),
])

Dans cet exemple, /user/([0-9]+) correspond à des URL comme /user/123. La partie ([0-9]+) capture un ou plusieurs chiffres et les passe comme argument user_id à la méthode get du UserHandler.

Modèles (Templating)

Tornado inclut un moteur de modèles simple et efficace. Les modèles sont utilisés pour générer du HTML dynamiquement, séparant la logique de présentation de la logique applicative.

Créer des Modèles :

Les modèles sont généralement stockés dans des fichiers séparés (par ex., index.html). Voici un exemple simple :

<!DOCTYPE html>
<html>
<head>
 <title>Mon Site Web</title>
</head>
<body>
 <h1>Bienvenue, {{ name }} !</h1>
 <p>Aujourd'hui, nous sommes le {{ today }}.</p>
</body>
</html>

Les {{ name }} et {{ today }} sont des balises de remplacement qui seront remplacées par des valeurs réelles lors du rendu du modèle.

Rendu des Modèles :

Pour effectuer le rendu d'un modèle, utilisez la méthode render() dans votre gestionnaire de requêtes :

class TemplateHandler(tornado.web.RequestHandler):
 def get(self):
  name = "John Doe"
  today = "2023-10-27"
  self.render("index.html", name=name, today=today)

Assurez-vous que le paramètre template_path est correctement configuré dans les paramètres de votre application. Par défaut, Tornado recherche les modèles dans un répertoire nommé templates situé dans le même répertoire que votre fichier d'application.

app = tornado.web.Application([
 (r"/template", TemplateHandler),
], template_path="templates")

Syntaxe des Modèles :

Les modèles Tornado prennent en charge diverses fonctionnalités, notamment :

Opérations Asynchrones

La force de Tornado réside dans ses capacités asynchrones. Les opérations asynchrones permettent à votre application d'effectuer des E/S non bloquantes, améliorant ainsi les performances et la scalabilité. C'est particulièrement utile pour les tâches qui impliquent d'attendre des ressources externes, comme des requêtes de base de données ou des requêtes réseau.

@tornado.gen.coroutine:

Le décorateur @tornado.gen.coroutine vous permet d'écrire du code asynchrone en utilisant le mot-clé yield. Cela rend le code asynchrone plus semblable au code synchrone en termes d'apparence et de comportement, améliorant la lisibilité et la maintenabilité.

import tornado.gen
import tornado.httpclient

class AsyncHandler(tornado.web.RequestHandler):
 @tornado.gen.coroutine
 def get(self):
  http_client = tornado.httpclient.AsyncHTTPClient()
  response = yield http_client.fetch("http://example.com")
  self.write(response.body.decode('utf-8'))

Dans cet exemple, http_client.fetch() est une opération asynchrone qui retourne un Future. Le mot-clé yield suspend l'exécution de la coroutine jusqu'à ce que le Future soit résolu. Une fois le Future résolu, la coroutine reprend et le corps de la réponse est écrit au client.

tornado.concurrent.Future:

Un Future représente le résultat d'une opération asynchrone qui n'est peut-être pas encore disponible. Vous pouvez utiliser les objets Future pour enchaîner des opérations asynchrones et gérer les erreurs.

tornado.ioloop.IOLoop:

L'IOLoop est le cœur du moteur asynchrone de Tornado. Il surveille les descripteurs de fichiers et les sockets pour les événements et les distribue aux gestionnaires appropriés. En général, vous n'avez pas besoin d'interagir directement avec l'IOLoop, mais il est important de comprendre son rôle dans la gestion des opérations asynchrones.

WebSockets

Tornado offre un excellent support pour les WebSockets, permettant une communication en temps réel entre le serveur et les clients. Les WebSockets sont idéaux pour les applications qui nécessitent une communication bidirectionnelle à faible latence, comme les applications de chat, les jeux en ligne et les tableaux de bord en temps réel.

Créer un Gestionnaire WebSocket :

Pour créer un gestionnaire WebSocket, héritez de la classe tornado.websocket.WebSocketHandler et implémentez les méthodes suivantes :

import tornado.websocket

class WebSocketHandler(tornado.websocket.WebSocketHandler):
 def open(self):
  print("WebSocket ouvert")

 def on_message(self, message):
  self.write_message(f"Vous avez envoyé : {message}")

 def on_close(self):
  print("WebSocket fermé")

 def check_origin(self, origin):
  return True # Activer les connexions WebSocket cross-origin

Intégrer les WebSockets dans Votre Application :

Ajoutez le gestionnaire WebSocket à la configuration de routage de votre application :

app = tornado.web.Application([
 (r"/ws", WebSocketHandler),
])

Implémentation Côté Client :

Côté client, vous pouvez utiliser JavaScript pour établir une connexion WebSocket et envoyer/recevoir des messages :

const websocket = new WebSocket("ws://localhost:8888/ws");

websocket.onopen = () => {
 console.log("Connexion WebSocket établie");
 websocket.send("Bonjour du client !");
};

websocket.onmessage = (event) => {
 console.log("Message reçu :", event.data);
};

websocket.onclose = () => {
 console.log("Connexion WebSocket fermée");
};

Authentification et Sécurité

La sécurité est un aspect critique du développement d'applications web. Tornado fournit plusieurs fonctionnalités pour vous aider à sécuriser vos applications, y compris l'authentification, l'autorisation et la protection contre les vulnérabilités web courantes.

Authentification :

L'authentification est le processus de vérification de l'identité d'un utilisateur. Tornado fournit un support intégré pour divers schémas d'authentification, notamment :

Autorisation :

L'autorisation est le processus qui consiste à déterminer si un utilisateur a la permission d'accéder à une ressource particulière. Vous pouvez implémenter la logique d'autorisation dans vos gestionnaires de requêtes pour restreindre l'accès en fonction des rôles ou des permissions des utilisateurs.

Bonnes Pratiques de Sécurité :

Déploiement

Le déploiement d'une application Tornado implique plusieurs étapes, notamment la configuration d'un serveur web, la mise en place d'un gestionnaire de processus et l'optimisation des performances.

Serveur Web :

Vous pouvez déployer Tornado derrière un serveur web comme Nginx ou Apache. Le serveur web agit comme un reverse proxy, transmettant les requêtes entrantes à l'application Tornado.

Gestionnaire de Processus :

Un gestionnaire de processus comme Supervisor ou systemd peut être utilisé pour gérer le processus Tornado, assurant son redémarrage automatique en cas de plantage.

Optimisation des Performances :

Internationalisation (i18n) et Localisation (l10n)

Lors de la création d'applications pour un public mondial, il est important de prendre en compte l'internationalisation (i18n) et la localisation (l10n). L'i18n est le processus de conception d'une application de manière à ce qu'elle puisse être adaptée à diverses langues et régions sans modifications techniques. La l10n est le processus d'adaptation d'une application internationalisée pour une langue ou une région spécifique en ajoutant des composants spécifiques à la locale et en traduisant le texte.

Tornado et i18n/l10n

Tornado lui-même n'a pas de bibliothèques i18n/l10n intégrées. Cependant, vous pouvez facilement intégrer des bibliothèques Python standard comme `gettext` ou des frameworks plus sophistiqués comme Babel pour gérer l'i18n/l10n au sein de votre application Tornado.

Exemple avec `gettext` :

1. **Configurez vos locales :** Créez des répertoires pour chaque langue que vous souhaitez prendre en charge, contenant des catalogues de messages (généralement des fichiers `.mo`).

locales/
 en/LC_MESSAGES/messages.mo
 fr/LC_MESSAGES/messages.mo
 de/LC_MESSAGES/messages.mo

2. **Extrayez les chaînes traduisibles :** Utilisez un outil comme `xgettext` pour extraire les chaînes traduisibles de votre code Python dans un fichier `.po` (Portable Object). Ce fichier contiendra les chaînes originales et les emplacements pour les traductions.

xgettext -d messages -o locales/messages.po votre_app_tornado.py

3. **Traduisez les chaînes :** Traduisez les chaînes dans les fichiers `.po` pour chaque langue.

4. **Compilez les traductions :** Compilez les fichiers `.po` en fichiers `.mo` (Machine Object) qui sont utilisés par `gettext` à l'exécution.

msgfmt locales/fr/LC_MESSAGES/messages.po -o locales/fr/LC_MESSAGES/messages.mo

5. **Intégrez dans votre application Tornado :**

import gettext
import locale
import os
import tornado.web

class BaseHandler(tornado.web.RequestHandler):
 def initialize(self):
  try:
  locale.setlocale(locale.LC_ALL, self.get_user_locale().code)
  except locale.Error:
  # Gérer les cas où la locale n'est pas supportée par le système
  print(f"Locale {self.get_user_locale().code} non supportée")

  translation = gettext.translation('messages', 'locales', languages=[self.get_user_locale().code])
  translation.install()
  self._ = translation.gettext

 def get_current_user_locale(self):
  # Logique pour déterminer la locale de l'utilisateur (ex: depuis l'en-tête Accept-Language, les paramètres utilisateur, etc.)
  # Ceci est un exemple simplifié - vous aurez besoin d'une solution plus robuste
  accept_language = self.request.headers.get('Accept-Language', 'en')
  return tornado.locale.get(accept_language.split(',')[0].split(';')[0])

class MainHandler(BaseHandler):
 def get(self):
  self.render("index.html", _=self._)

settings = {
 "template_path": os.path.join(os.path.dirname(__file__), "templates"),
}

app = tornado.web.Application([
 (r"/", MainHandler),
], **settings)

6. **Modifiez vos modèles :** Utilisez la fonction `_()` (liée à `gettext.gettext`) pour marquer les chaînes à traduire dans vos modèles.

<h1>{{ _("Bienvenue sur notre site web !") }}</h1>
<p>{{ _("Ceci est un paragraphe traduit.") }}</p>

Considérations Importantes pour un Public Mondial :

Sujets Avancés

Pages d'Erreur Personnalisées :

Vous pouvez personnaliser les pages d'erreur que Tornado affiche lorsqu'une erreur se produit. Cela vous permet de fournir une expérience plus conviviale et d'inclure des informations de débogage.

Paramètres Personnalisés :

Vous pouvez définir des paramètres personnalisés dans la configuration de votre application et y accéder dans vos gestionnaires de requêtes. C'est utile pour stocker des paramètres spécifiques à l'application, tels que les chaînes de connexion à la base de données ou les clés d'API.

Tests :

Testez minutieusement vos applications Tornado pour vous assurer qu'elles fonctionnent correctement et en toute sécurité. Utilisez des tests unitaires, des tests d'intégration et des tests de bout en bout pour couvrir tous les aspects de votre application.

Conclusion

Tornado est un framework web puissant et polyvalent, bien adapté pour créer des applications web évolutives et performantes. Son architecture asynchrone, son support des WebSockets et son API facile à utiliser en font un choix populaire pour les développeurs du monde entier. En suivant les directives et les exemples de ce guide complet, vous pouvez commencer à créer vos propres applications Tornado et tirer parti de ses nombreuses fonctionnalités.

N'oubliez pas de consulter la documentation officielle de Tornado pour les informations les plus à jour et les meilleures pratiques. Bon codage !