Een diepgaande verkenning van Tornado, een Python webframework en asynchrone netwerkbibliotheek. Leer hoe u schaalbare, high-performance applicaties bouwt met gedetailleerde uitleg, voorbeelden en best practices.
Tornado Documentatie: Een Uitgebreide Gids voor Ontwikkelaars Wereldwijd
Tornado is een Python webframework en asynchrone netwerkbibliotheek, oorspronkelijk ontwikkeld bij FriendFeed. Het is bijzonder geschikt voor long-polling, WebSockets en andere applicaties die een langdurige verbinding met elke gebruiker vereisen. De niet-blokkerende netwerk I/O maakt het extreem schaalbaar en een krachtige keuze voor het bouwen van high-performance webapplicaties. Deze uitgebreide gids leidt u door de kernconcepten van Tornado en biedt praktische voorbeelden om u op weg te helpen.
Wat is Tornado?
In de kern is Tornado een webframework en een asynchrone netwerkbibliotheek. In tegenstelling tot traditionele synchrone webframeworks, gebruikt Tornado een single-threaded, event-loop-gebaseerde architectuur. Dit betekent dat het veel gelijktijdige verbindingen kan afhandelen zonder een thread per verbinding te vereisen, wat het efficiënter en schaalbaarder maakt.
Belangrijkste Kenmerken van Tornado:
- Asynchroon Netwerken: De kern van Tornado is opgebouwd rond asynchrone I/O, waardoor het duizenden gelijktijdige verbindingen efficiënt kan afhandelen.
- Webframework: Het bevat functies zoals request handlers, routing, templating en authenticatie, wat het een compleet webframework maakt.
- WebSocket-ondersteuning: Tornado biedt uitstekende ondersteuning voor WebSockets, waardoor real-time communicatie tussen de server en clients mogelijk wordt.
- Lichtgewicht en Snel: Ontworpen voor prestaties, is Tornado lichtgewicht en efficiënt, waardoor overhead wordt geminimaliseerd en de doorvoer wordt gemaximaliseerd.
- Eenvoudig in Gebruik: Ondanks zijn geavanceerde functies is Tornado relatief eenvoudig te leren en te gebruiken, met een duidelijke en goed gedocumenteerde API.
Uw Tornado-omgeving Opzetten
Voordat u begint met de ontwikkeling van Tornado, moet u uw omgeving opzetten. Hier is een stapsgewijze handleiding:
- Installeer Python: Zorg ervoor dat u Python 3.6 of hoger hebt geïnstalleerd. U kunt het downloaden van de officiële Python-website (python.org).
- Maak een Virtuele Omgeving (Aanbevolen): Gebruik
venv
ofvirtualenv
om een geïsoleerde omgeving voor uw project te maken:python3 -m venv myenv source myenv/bin/activate # Op Linux/macOS myenv\Scripts\activate # Op Windows
- Installeer Tornado: Installeer Tornado met pip:
pip install tornado
Uw Eerste Tornado-applicatie
Laten we een eenvoudige "Hello, World!"-applicatie maken met Tornado. Maak een bestand met de naam app.py
en voeg de volgende code toe:
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()
Voer nu de applicatie uit vanaf uw terminal:
python app.py
Open uw webbrowser en navigeer naar http://localhost:8888
. U zou het "Hello, World!"-bericht moeten zien.
Uitleg:
tornado.ioloop
: De kern event-loop die asynchrone operaties afhandelt.tornado.web
: Biedt de webframeworkcomponenten, zoals request handlers en routing.MainHandler
: Een request handler die definieert hoe inkomende HTTP-verzoeken moeten worden afgehandeld. Deget()
-methode wordt aangeroepen voor GET-verzoeken.tornado.web.Application
: Creëert de Tornado-applicatie, waarbij URL-patronen aan request handlers worden gekoppeld.app.listen(8888)
: Start de server, die luistert naar inkomende verbindingen op poort 8888.tornado.ioloop.IOLoop.current().start()
: Start de event-loop, die inkomende verzoeken verwerkt en asynchrone operaties afhandelt.
Request Handlers en Routing
Request handlers vormen de basis van Tornado-webapplicaties. Ze definiëren hoe inkomende HTTP-verzoeken moeten worden afgehandeld op basis van de URL. Routing koppelt URL's aan specifieke request handlers.
Request Handlers Definiëren:
Om een request handler te maken, subklasseer tornado.web.RequestHandler
en implementeer de juiste HTTP-methoden (get
, post
, put
, delete
, etc.).
class MyHandler(tornado.web.RequestHandler):
def get(self):
self.write("This is a GET request.")
def post(self):
data = self.request.body.decode('utf-8')
self.write(f"Received POST data: {data}")
Routing:
Routing wordt geconfigureerd bij het aanmaken van de tornado.web.Application
. U geeft een lijst van tupels op, waarbij elk tupel een URL-patroon en de bijbehorende request handler bevat.
app = tornado.web.Application([
(r"/", MainHandler),
(r"/myhandler", MyHandler),
])
URL-patronen:
URL-patronen zijn reguliere expressies. U kunt groepen van reguliere expressies gebruiken om delen van de URL vast te leggen en deze als argumenten door te geven aan de methoden van de request handler.
class UserHandler(tornado.web.RequestHandler):
def get(self, user_id):
self.write(f"User ID: {user_id}")
app = tornado.web.Application([
(r"/user/([0-9]+)", UserHandler),
])
In dit voorbeeld komt /user/([0-9]+)
overeen met URL's zoals /user/123
. Het deel ([0-9]+)
legt een of meer cijfers vast en geeft deze als het user_id
-argument door aan de get
-methode van de UserHandler
.
Templating
Tornado bevat een eenvoudige en efficiënte templating engine. Templates worden gebruikt om HTML dynamisch te genereren, waardoor presentatielogica wordt gescheiden van applicatielogica.
Templates Maken:
Templates worden doorgaans opgeslagen in afzonderlijke bestanden (bijv. index.html
). Hier is een eenvoudig voorbeeld:
<!DOCTYPE html>
<html>
<head>
<title>Mijn Website</title>
</head>
<body>
<h1>Welkom, {{ name }}!</h1>
<p>Vandaag is het {{ today }}.</p>
</body>
</html>
De {{ name }}
en {{ today }}
zijn placeholders die worden vervangen door de werkelijke waarden wanneer de template wordt gerenderd.
Templates Renderen:
Om een template te renderen, gebruikt u de render()
-methode in uw request handler:
class TemplateHandler(tornado.web.RequestHandler):
def get(self):
name = "John Doe"
today = "2023-10-27"
self.render("index.html", name=name, today=today)
Zorg ervoor dat de template_path
-instelling correct is geconfigureerd in uw applicatie-instellingen. Standaard zoekt Tornado naar templates in een map met de naam templates
in dezelfde map als uw applicatiebestand.
app = tornado.web.Application([
(r"/template", TemplateHandler),
], template_path="templates")
Template Syntaxis:
Tornado-templates ondersteunen verschillende functies, waaronder:
- Variabelen:
{{ variable }}
- Controlestructuren:
{% if condition %} ... {% else %} ... {% end %}
,{% for item in items %} ... {% end %}
- Functies:
{{ function(argument) }}
- Includes:
{% include "another_template.html" %}
- Escaping: Tornado escapet automatisch HTML-entiteiten om cross-site scripting (XSS)-aanvallen te voorkomen. U kunt escaping uitschakelen met
{% raw variable %}
.
Asynchrone Operaties
De kracht van Tornado ligt in zijn asynchrone capaciteiten. Asynchrone operaties stellen uw applicatie in staat om niet-blokkerende I/O uit te voeren, wat de prestaties en schaalbaarheid verbetert. Dit is met name handig voor taken die wachten op externe bronnen, zoals databasequery's of netwerkverzoeken.
@tornado.gen.coroutine
:
De @tornado.gen.coroutine
-decorator stelt u in staat om asynchrone code te schrijven met het yield
-sleutelwoord. Dit zorgt ervoor dat asynchrone code er meer uitziet en zich gedraagt als synchrone code, wat de leesbaarheid en onderhoudbaarheid verbetert.
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'))
In dit voorbeeld is http_client.fetch()
een asynchrone operatie die een Future
retourneert. Het yield
-sleutelwoord schort de uitvoering van de coroutine op totdat de Future
is opgelost. Zodra de Future
is opgelost, wordt de coroutine hervat en wordt de response body naar de client geschreven.
tornado.concurrent.Future
:
Een Future
vertegenwoordigt het resultaat van een asynchrone operatie die mogelijk nog niet beschikbaar is. U kunt Future
-objecten gebruiken om asynchrone operaties aan elkaar te koppelen en fouten af te handelen.
tornado.ioloop.IOLoop
:
De IOLoop
is het hart van Tornado's asynchrone engine. Het monitort bestandsdescriptoren en sockets op gebeurtenissen en stuurt deze door naar de juiste handlers. U hoeft doorgaans niet rechtstreeks met de IOLoop
te communiceren, maar het is belangrijk om de rol ervan bij het afhandelen van asynchrone operaties te begrijpen.
WebSockets
Tornado biedt uitstekende ondersteuning voor WebSockets, waardoor real-time communicatie tussen de server en clients mogelijk wordt. WebSockets zijn ideaal voor applicaties die bidirectionele, lage-latentie communicatie vereisen, zoals chat-applicaties, online games en real-time dashboards.
Een WebSocket Handler Maken:
Om een WebSocket handler te maken, subklasseer tornado.websocket.WebSocketHandler
en implementeer de volgende methoden:
open()
: Wordt aangeroepen wanneer een nieuwe WebSocket-verbinding wordt opgezet.on_message(message)
: Wordt aangeroepen wanneer een bericht van de client wordt ontvangen.on_close()
: Wordt aangeroepen wanneer de WebSocket-verbinding wordt gesloten.
import tornado.websocket
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
print("WebSocket geopend")
def on_message(self, message):
self.write_message(f"U stuurde: {message}")
def on_close(self):
print("WebSocket gesloten")
def check_origin(self, origin):
return True # Schakel cross-origin WebSocket-verbindingen in
WebSockets Integreren in uw Applicatie:
Voeg de WebSocket handler toe aan de routingconfiguratie van uw applicatie:
app = tornado.web.Application([
(r"/ws", WebSocketHandler),
])
Client-Side Implementatie:
Aan de client-zijde kunt u JavaScript gebruiken om een WebSocket-verbinding op te zetten en berichten te verzenden/ontvangen:
const websocket = new WebSocket("ws://localhost:8888/ws");
websocket.onopen = () => {
console.log("WebSocket-verbinding opgezet");
websocket.send("Hallo vanaf de client!");
};
websocket.onmessage = (event) => {
console.log("Bericht ontvangen:", event.data);
};
websocket.onclose = () => {
console.log("WebSocket-verbinding gesloten");
};
Authenticatie en Beveiliging
Beveiliging is een cruciaal aspect van webapplicatieontwikkeling. Tornado biedt verschillende functies om u te helpen uw applicaties te beveiligen, waaronder authenticatie, autorisatie en bescherming tegen veelvoorkomende webkwetsbaarheden.
Authenticatie:
Authenticatie is het proces van het verifiëren van de identiteit van een gebruiker. Tornado biedt ingebouwde ondersteuning voor verschillende authenticatiemethoden, waaronder:
- Cookie-gebaseerde authenticatie: Sla gebruikersgegevens op in cookies.
- Authenticatie door derden (OAuth): Integreer met populaire sociale mediaplatforms zoals Google, Facebook en Twitter.
- API-sleutels: Gebruik API-sleutels voor het authenticeren van API-verzoeken.
Autorisatie:
Autorisatie is het proces om te bepalen of een gebruiker toestemming heeft om toegang te krijgen tot een bepaalde bron. U kunt autorisatielogica implementeren in uw request handlers om de toegang te beperken op basis van gebruikersrollen of permissies.
Best Practices voor Beveiliging:
- Bescherming tegen Cross-Site Scripting (XSS): Tornado escapet automatisch HTML-entiteiten om XSS-aanvallen te voorkomen. Gebruik altijd de
render()
-methode om templates te renderen en vermijd het direct genereren van HTML in uw request handlers. - Bescherming tegen Cross-Site Request Forgery (CSRF): Schakel CSRF-bescherming in uw applicatie-instellingen in om CSRF-aanvallen te voorkomen.
- HTTPS: Gebruik altijd HTTPS om de communicatie tussen de server en clients te versleutelen.
- Invoervalidatie: Valideer alle gebruikersinvoer om injectieaanvallen en andere kwetsbaarheden te voorkomen.
- Regelmatige Beveiligingsaudits: Voer regelmatig beveiligingsaudits uit om potentiële kwetsbaarheden te identificeren en aan te pakken.
Deployment
Het deployen van een Tornado-applicatie omvat verschillende stappen, waaronder het configureren van een webserver, het opzetten van een procesmanager en het optimaliseren van de prestaties.
Webserver:
U kunt Tornado achter een webserver zoals Nginx of Apache deployen. De webserver fungeert als een reverse proxy, die inkomende verzoeken doorstuurt naar de Tornado-applicatie.
Procesmanager:
Een procesmanager zoals Supervisor of systemd kan worden gebruikt om het Tornado-proces te beheren, zodat het automatisch opnieuw wordt opgestart als het crasht.
Prestatieoptimalisatie:
- Gebruik een Productieklare Event Loop: Gebruik een productieklare event loop zoals
uvloop
voor betere prestaties. - Schakel gzip-compressie in: Schakel gzip-compressie in om de grootte van HTTP-responses te verkleinen.
- Cache Statische Bestanden: Cache statische bestanden om de belasting op de server te verminderen.
- Monitor Prestaties: Monitor de prestaties van uw applicatie met tools zoals New Relic of Prometheus.
Internationalisatie (i18n) en Lokalisatie (l10n)
Bij het bouwen van applicaties voor een wereldwijd publiek is het belangrijk om rekening te houden met internationalisatie (i18n) en lokalisatie (l10n). i18n is het proces van het ontwerpen van een applicatie zodat deze kan worden aangepast aan verschillende talen en regio's zonder technische wijzigingen. l10n is het proces van het aanpassen van een geïnternationaliseerde applicatie voor een specifieke taal of regio door landspecifieke componenten toe te voegen en tekst te vertalen.
Tornado en i18n/l10n
Tornado zelf heeft geen ingebouwde i18n/l10n-bibliotheken. U kunt echter eenvoudig standaard Python-bibliotheken zoals `gettext` of meer geavanceerde frameworks zoals Babel integreren om i18n/l10n binnen uw Tornado-applicatie af te handelen.
Voorbeeld met `gettext`:
1. **Stel uw locales in:** Maak mappen voor elke taal die u wilt ondersteunen, met daarin berichtencatalogi (meestal `.mo`-bestanden).
locales/
en/LC_MESSAGES/messages.mo
fr/LC_MESSAGES/messages.mo
de/LC_MESSAGES/messages.mo
2. **Extraheer vertaalbare strings:** Gebruik een tool zoals `xgettext` om vertaalbare strings uit uw Python-code te extraheren naar een `.po`-bestand (Portable Object). Dit bestand bevat de originele strings en placeholders voor vertalingen.
xgettext -d messages -o locales/messages.po your_tornado_app.py
3. **Vertaal de strings:** Vertaal de strings in de `.po`-bestanden voor elke taal.
4. **Compileer de vertalingen:** Compileer de `.po`-bestanden naar `.mo`-bestanden (Machine Object) die tijdens runtime door `gettext` worden gebruikt.
msgfmt locales/fr/LC_MESSAGES/messages.po -o locales/fr/LC_MESSAGES/messages.mo
5. **Integreer in uw Tornado-applicatie:**
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:
# Behandel gevallen waarin de locale niet wordt ondersteund door het systeem
print(f"Locale {self.get_user_locale().code} niet ondersteund")
translation = gettext.translation('messages', 'locales', languages=[self.get_user_locale().code])
translation.install()
self._ = translation.gettext
def get_current_user_locale(self):
# Logica om de locale van de gebruiker te bepalen (bijv. uit Accept-Language header, gebruikersinstellingen, etc.)
# Dit is een vereenvoudigd voorbeeld - u heeft een robuustere oplossing nodig
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. **Pas uw templates aan:** Gebruik de `_()`-functie (gekoppeld aan `gettext.gettext`) om strings voor vertaling in uw templates te markeren.
<h1>{{ _("Welkom op onze website!") }}</h1>
<p>{{ _("Dit is een vertaalde paragraaf.") }}</p>
Belangrijke Overwegingen voor een Wereldwijd Publiek:
- **Karaktercodering:** Gebruik altijd UTF-8-codering om een breed scala aan karakters te ondersteunen.
- **Datum- en Tijdnotatie:** Gebruik landspecifieke datum- en tijdnotatie. Python's `strftime`- en `strptime`-functies kunnen worden gebruikt met locale-instellingen.
- **Getalnotatie:** Gebruik landspecifieke getalnotatie (bijv. decimale scheidingstekens, duizendtalscheidingstekens). De `locale`-module biedt hier functies voor.
- **Valutanotatie:** Gebruik landspecifieke valutanotatie. Overweeg het gebruik van een bibliotheek zoals `Babel` voor meer geavanceerde valutabehandeling.
- **Rechts-naar-Links (RTL) Talen:** Ondersteun RTL-talen zoals Arabisch en Hebreeuws. Dit kan het spiegelen van de lay-out van uw website inhouden.
- **Vertaalkwaliteit:** Gebruik professionele vertalers om nauwkeurige en cultureel passende vertalingen te garanderen. Machinevertaling kan een goed startpunt zijn, maar vereist vaak menselijke beoordeling.
- **Detectie van Gebruikerslocale:** Implementeer robuuste locale-detectie op basis van gebruikersvoorkeuren, browserinstellingen of IP-adres. Bied gebruikers een manier om handmatig hun voorkeurstaal te selecteren.
- **Testen:** Test uw applicatie grondig met verschillende locales om ervoor te zorgen dat alles correct wordt weergegeven.
Geavanceerde Onderwerpen
Aangepaste Foutpagina's:
U kunt de foutpagina's die Tornado weergeeft wanneer er een fout optreedt, aanpassen. Dit stelt u in staat om een gebruiksvriendelijkere ervaring te bieden en foutopsporingsinformatie op te nemen.
Aangepaste Instellingen:
U kunt aangepaste instellingen definiëren in uw applicatieconfiguratie en deze openen in uw request handlers. Dit is handig voor het opslaan van applicatiespecifieke parameters, zoals databaseverbindingsreeksen of API-sleutels.
Testen:
Test uw Tornado-applicaties grondig om ervoor te zorgen dat ze correct en veilig functioneren. Gebruik unit tests, integratietests en end-to-end tests om alle aspecten van uw applicatie te dekken.
Conclusie
Tornado is een krachtig en veelzijdig webframework dat zeer geschikt is voor het bouwen van schaalbare, high-performance webapplicaties. De asynchrone architectuur, WebSocket-ondersteuning en gebruiksvriendelijke API maken het een populaire keuze voor ontwikkelaars wereldwijd. Door de richtlijnen en voorbeelden in deze uitgebreide gids te volgen, kunt u beginnen met het bouwen van uw eigen Tornado-applicaties en profiteren van de vele functies.
Vergeet niet de officiële Tornado-documentatie te raadplegen voor de meest actuele informatie en best practices. Veel codeerplezier!