En djupgÄende utforskning av Tornado, ett webbramverk och asynkront nÀtverksbibliotek för Python. LÀr dig bygga skalbara, högpresterande applikationer med detaljerade förklaringar, exempel och bÀsta praxis.
Tornado-dokumentation: En omfattande guide för utvecklare vÀrlden över
Tornado Àr ett webbramverk och asynkront nÀtverksbibliotek för Python, ursprungligen utvecklat pÄ FriendFeed. Det Àr sÀrskilt vÀl lÀmpat för long-polling, WebSockets och andra applikationer som krÀver en lÄngvarig anslutning till varje anvÀndare. Dess icke-blockerande nÀtverks-I/O gör det extremt skalbart och ett kraftfullt val för att bygga högpresterande webbapplikationer. Denna omfattande guide kommer att leda dig genom Tornados kÀrnkoncept och ge praktiska exempel för att komma igÄng.
Vad Àr Tornado?
I grunden Àr Tornado ett webbramverk och asynkront nÀtverksbibliotek. Till skillnad frÄn traditionella synkrona webbramverk anvÀnder Tornado en entrÄdad, hÀndelseloop-baserad arkitektur. Detta innebÀr att det kan hantera mÄnga samtidiga anslutningar utan att krÀva en trÄd per anslutning, vilket gör det mer effektivt och skalbart.
Nyckelfunktioner i Tornado:
- Asynkront nÀtverk: Tornados kÀrna Àr byggd kring asynkron I/O, vilket gör att det effektivt kan hantera tusentals samtidiga anslutningar.
- Webbramverk: Det inkluderar funktioner som request handlers, routing, mallhantering och autentisering, vilket gör det till ett komplett webbramverk.
- Stöd för WebSockets: Tornado erbjuder utmÀrkt stöd för WebSockets, vilket möjliggör realtidskommunikation mellan servern och klienter.
- LÀttviktigt och snabbt: Designat för prestanda Àr Tornado lÀttviktigt och effektivt, vilket minimerar overhead och maximerar genomströmning.
- LÀtt att anvÀnda: Trots sina avancerade funktioner Àr Tornado relativt lÀtt att lÀra sig och anvÀnda, med ett tydligt och vÀldokumenterat API.
Konfigurera din Tornado-miljö
Innan du dyker in i Tornado-utveckling mÄste du konfigurera din miljö. HÀr Àr en steg-för-steg-guide:
- Installera Python: Se till att du har Python 3.6 eller högre installerat. Du kan ladda ner det frÄn den officiella Python-webbplatsen (python.org).
- Skapa en virtuell miljö (rekommenderas): AnvÀnd
venvellervirtualenvför att skapa en isolerad miljö för ditt projekt:python3 -m venv myenv source myenv/bin/activate # PÄ Linux/macOS myenv\Scripts\activate # PÄ Windows - Installera Tornado: Installera Tornado med pip:
pip install tornado
Din första Tornado-applikation
LÄt oss skapa en enkel "Hej, VÀrlden!"-applikation med Tornado. Skapa en fil med namnet app.py och lÀgg till följande kod:
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hej, VĂ€rlden!")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Kör nu applikationen frÄn din terminal:
python app.py
Ăppna din webblĂ€sare och navigera till http://localhost:8888. Du bör se meddelandet "Hej, VĂ€rlden!".
Förklaring:
tornado.ioloop: KÀrn-hÀndelseloopen som hanterar asynkrona operationer.tornado.web: TillhandahÄller webbramverkets komponenter, sÄsom request handlers och routing.MainHandler: En request handler som definierar hur inkommande HTTP-förfrÄgningar ska hanteras. Metodenget()anropas för GET-förfrÄgningar.tornado.web.Application: Skapar Tornado-applikationen och mappar URL-mönster till request handlers.app.listen(8888): Startar servern som lyssnar efter inkommande anslutningar pÄ port 8888.tornado.ioloop.IOLoop.current().start(): Startar hÀndelseloopen, som bearbetar inkommande förfrÄgningar och hanterar asynkrona operationer.
Request Handlers och Routing
Request handlers Àr grunden för Tornado-webbapplikationer. De definierar hur man hanterar inkommande HTTP-förfrÄgningar baserat pÄ URL:en. Routing mappar URL:er till specifika request handlers.
Definiera Request Handlers:
För att skapa en request handler, subklassa tornado.web.RequestHandler och implementera lÀmpliga HTTP-metoder (get, post, put, delete, etc.).
class MyHandler(tornado.web.RequestHandler):
def get(self):
self.write("Detta Àr en GET-förfrÄgan.")
def post(self):
data = self.request.body.decode('utf-8')
self.write(f"Mottagen POST-data: {data}")
Routing:
Routing konfigureras nÀr tornado.web.Application skapas. Du anger en lista med tupler, dÀr varje tupel innehÄller ett URL-mönster och motsvarande request handler.
app = tornado.web.Application([
(r"/", MainHandler),
(r"/myhandler", MyHandler),
])
URL-mönster:
URL-mönster Àr reguljÀra uttryck. Du kan anvÀnda grupper i reguljÀra uttryck för att fÄnga delar av URL:en och skicka dem som argument till request handler-metoderna.
class UserHandler(tornado.web.RequestHandler):
def get(self, user_id):
self.write(f"AnvÀndar-ID: {user_id}")
app = tornado.web.Application([
(r"/user/([0-9]+)", UserHandler),
])
I detta exempel matchar /user/([0-9]+) URL:er som /user/123. Delen ([0-9]+) fÄngar en eller flera siffror och skickar dem som argumentet user_id till get-metoden i UserHandler.
Mallhantering (Templating)
Tornado inkluderar en enkel och effektiv mallmotor. Mallar anvÀnds för att generera HTML dynamiskt och separerar presentationslogik frÄn applikationslogik.
Skapa mallar:
Mallar lagras vanligtvis i separata filer (t.ex. index.html). HÀr Àr ett enkelt exempel:
<!DOCTYPE html>
<html>
<head>
<title>Min webbplats</title>
</head>
<body>
<h1>VĂ€lkommen, {{ name }}!</h1>
<p>Idag Àr det {{ today }}.</p>
</body>
</html>
{{ name }} och {{ today }} Àr platshÄllare som kommer att ersÀttas med faktiska vÀrden nÀr mallen renderas.
Rendera mallar:
För att rendera en mall, anvÀnd render()-metoden i din 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)
Se till att instÀllningen template_path Àr korrekt konfigurerad i dina applikationsinstÀllningar. Som standard letar Tornado efter mallar i en katalog med namnet templates i samma katalog som din applikationsfil.
app = tornado.web.Application([
(r"/template", TemplateHandler),
], template_path="templates")
Mallsyntax:
Tornado-mallar stöder olika funktioner, inklusive:
- Variabler:
{{ variable }} - Kontrollflöde:
{% if condition %} ... {% else %} ... {% end %},{% for item in items %} ... {% end %} - Funktioner:
{{ function(argument) }} - Inkluderingar:
{% include "another_template.html" %} - Escaping: Tornado escapar automatiskt HTML-entiteter för att förhindra cross-site scripting (XSS)-attacker. Du kan inaktivera escaping med
{% raw variable %}.
Asynkrona operationer
Tornados styrka ligger i dess asynkrona kapabiliteter. Asynkrona operationer lÄter din applikation utföra icke-blockerande I/O, vilket förbÀttrar prestanda och skalbarhet. Detta Àr sÀrskilt anvÀndbart för uppgifter som involverar vÀntan pÄ externa resurser, sÄsom databasfrÄgor eller nÀtverksanrop.
@tornado.gen.coroutine:
Dekoratorn @tornado.gen.coroutine lÄter dig skriva asynkron kod med nyckelordet yield. Detta gör att asynkron kod ser ut och beter sig mer som synkron kod, vilket förbÀttrar lÀsbarheten och underhÄllbarheten.
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'))
I detta exempel Àr http_client.fetch() en asynkron operation som returnerar en Future. Nyckelordet yield pausar exekveringen av coroutinen tills Future-objektet Àr löst. NÀr Future-objektet Àr löst Äterupptas coroutinen och svarskroppen skrivs till klienten.
tornado.concurrent.Future:
En Future representerar resultatet av en asynkron operation som kanske inte Àr tillgÀngligt Ànnu. Du kan anvÀnda Future-objekt för att kedja samman asynkrona operationer och hantera fel.
tornado.ioloop.IOLoop:
IOLoop Àr hjÀrtat i Tornados asynkrona motor. Den övervakar filbeskrivare och sockets för hÀndelser och skickar dem till lÀmpliga handlers. Du behöver vanligtvis inte interagera med IOLoop direkt, men det Àr viktigt att förstÄ dess roll i hanteringen av asynkrona operationer.
WebSockets
Tornado erbjuder utmÀrkt stöd för WebSockets, vilket möjliggör realtidskommunikation mellan servern och klienter. WebSockets Àr idealiska för applikationer som krÀver dubbelriktad kommunikation med lÄg latens, sÄsom chattapplikationer, onlinespel och realtids-dashboards.
Skapa en WebSocket Handler:
För att skapa en WebSocket-handler, subklassa tornado.websocket.WebSocketHandler och implementera följande metoder:
open(): Anropas nÀr en ny WebSocket-anslutning etableras.on_message(message): Anropas nÀr ett meddelande tas emot frÄn klienten.on_close(): Anropas nÀr WebSocket-anslutningen stÀngs.
import tornado.websocket
class WebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
print("WebSocket öpnad")
def on_message(self, message):
self.write_message(f"Du skickade: {message}")
def on_close(self):
print("WebSocket stÀngd")
def check_origin(self, origin):
return True # Aktivera cross-origin WebSocket-anslutningar
Integrera WebSockets i din applikation:
LĂ€gg till WebSocket-handlern i din applikations routing-konfiguration:
app = tornado.web.Application([
(r"/ws", WebSocketHandler),
])
Implementation pÄ klientsidan:
PÄ klientsidan kan du anvÀnda JavaScript för att etablera en WebSocket-anslutning och skicka/ta emot meddelanden:
const websocket = new WebSocket("ws://localhost:8888/ws");
websocket.onopen = () => {
console.log("WebSocket-anslutning etablerad");
websocket.send("Hej frÄn klienten!");
};
websocket.onmessage = (event) => {
console.log("Meddelande mottaget:", event.data);
};
websocket.onclose = () => {
console.log("WebSocket-anslutning stÀngd");
};
Autentisering och sÀkerhet
SÀkerhet Àr en kritisk aspekt av webbapplikationsutveckling. Tornado tillhandahÄller flera funktioner för att hjÀlpa dig att sÀkra dina applikationer, inklusive autentisering, auktorisering och skydd mot vanliga webbsÄrbarheter.
Autentisering:
Autentisering Àr processen att verifiera en anvÀndares identitet. Tornado har inbyggt stöd för olika autentiseringsscheman, inklusive:
- Cookie-baserad autentisering: Lagra anvÀndaruppgifter i cookies.
- Tredjepartsautentisering (OAuth): Integrera med populÀra sociala medieplattformar som Google, Facebook och Twitter.
- API-nycklar: AnvÀnd API-nycklar för att autentisera API-förfrÄgningar.
Auktorisering:
Auktorisering Àr processen att avgöra om en anvÀndare har behörighet att komma Ät en viss resurs. Du kan implementera auktoriseringslogik i dina request handlers för att begrÀnsa Ätkomst baserat pÄ anvÀndarroller eller behörigheter.
BÀsta praxis för sÀkerhet:
- Skydd mot Cross-Site Scripting (XSS): Tornado escapar automatiskt HTML-entiteter för att förhindra XSS-attacker. AnvÀnd alltid
render()-metoden för att rendera mallar och undvik att generera HTML direkt i dina request handlers. - Skydd mot Cross-Site Request Forgery (CSRF): Aktivera CSRF-skydd i dina applikationsinstÀllningar för att förhindra CSRF-attacker.
- HTTPS: AnvÀnd alltid HTTPS för att kryptera kommunikationen mellan servern och klienterna.
- Indatavalidering: Validera all anvÀndarinmatning för att förhindra injektionsattacker och andra sÄrbarheter.
- Regelbundna sÀkerhetsrevisioner: Genomför regelbundna sÀkerhetsrevisioner för att identifiera och ÄtgÀrda potentiella sÄrbarheter.
DriftsÀttning (Deployment)
Att driftsÀtta en Tornado-applikation innefattar flera steg, inklusive att konfigurera en webbserver, sÀtta upp en processhanterare och optimera prestanda.
Webbserver:
Du kan driftsÀtta Tornado bakom en webbserver som Nginx eller Apache. Webbservern fungerar som en omvÀnd proxy och vidarebefordrar inkommande förfrÄgningar till Tornado-applikationen.
Processhanterare:
En processhanterare som Supervisor eller systemd kan anvÀndas för att hantera Tornado-processen och sÀkerstÀlla att den startas om automatiskt om den kraschar.
Prestandaoptimering:
- AnvÀnd en produktionsklar hÀndelseloop: AnvÀnd en produktionsklar hÀndelseloop som
uvloopför förbÀttrad prestanda. - Aktivera gzip-komprimering: Aktivera gzip-komprimering för att minska storleken pÄ HTTP-svar.
- Cacha statiska filer: Cacha statiska filer för att minska belastningen pÄ servern.
- Ăvervaka prestanda: Ăvervaka prestandan för din applikation med verktyg som New Relic eller Prometheus.
Internationalisering (i18n) och lokalisering (l10n)
NÀr man bygger applikationer för en global publik Àr det viktigt att ta hÀnsyn till internationalisering (i18n) och lokalisering (l10n). i18n Àr processen att designa en applikation sÄ att den kan anpassas till olika sprÄk och regioner utan tekniska Àndringar. l10n Àr processen att anpassa en internationaliserad applikation för ett specifikt sprÄk eller en specifik region genom att lÀgga till lokalspecifika komponenter och översÀtta text.
Tornado och i18n/l10n
Tornado har inga inbyggda i18n/l10n-bibliotek. DÀremot kan du enkelt integrera standardbibliotek i Python som `gettext` eller mer sofistikerade ramverk som Babel för att hantera i18n/l10n i din Tornado-applikation.
Exempel med gettext:
1. **Konfigurera dina locales:** Skapa kataloger för varje sprÄk du vill stödja, innehÄllande meddelandekataloger (vanligtvis `.mo`-filer).
locales/
en/LC_MESSAGES/messages.mo
fr/LC_MESSAGES/messages.mo
de/LC_MESSAGES/messages.mo
2. **Extrahera översÀttningsbara strÀngar:** AnvÀnd ett verktyg som xgettext för att extrahera översÀttningsbara strÀngar frÄn din Python-kod till en `.po`-fil (Portable Object). Denna fil kommer att innehÄlla originalstrÀngarna och platshÄllare för översÀttningar.
xgettext -d messages -o locales/messages.po your_tornado_app.py
3. **ĂversĂ€tt strĂ€ngarna:** ĂversĂ€tt strĂ€ngarna i `.po`-filerna för varje sprĂ„k.
4. **Kompilera översÀttningarna:** Kompilera `.po`-filerna till `.mo`-filer (Machine Object) som anvÀnds av `gettext` vid körtid.
msgfmt locales/fr/LC_MESSAGES/messages.po -o locales/fr/LC_MESSAGES/messages.mo
5. **Integrera i din Tornado-applikation:**
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:
# Hantera fall dÀr locale inte stöds av systemet
print(f"Locale {self.get_user_locale().code} stöds inte")
translation = gettext.translation('messages', 'locales', languages=[self.get_user_locale().code])
translation.install()
self._ = translation.gettext
def get_current_user_locale(self):
# Logik för att bestÀmma anvÀndarens locale (t.ex. frÄn Accept-Language-header, anvÀndarinstÀllningar, etc.)
# Detta Àr ett förenklat exempel - du behöver en mer robust lösning
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. **Modifiera dina mallar:** AnvÀnd funktionen `_()` (bunden till `gettext.gettext`) för att markera strÀngar för översÀttning i dina mallar.
<h1>{{ _("VÀlkommen till vÄr webbplats!") }}</h1>
<p>{{ _("Detta Àr ett översatt stycke.") }}</p>
Viktiga övervÀganden för en global publik:
- **Teckenkodning:** AnvÀnd alltid UTF-8-kodning för att stödja ett brett utbud av tecken.
- **Datum- och tidsformatering:** AnvÀnd lokalspecifik datum- och tidsformatering. Pythons funktioner `strftime` och `strptime` kan anvÀndas med locale-instÀllningar.
- **Talformatering:** AnvÀnd lokalspecifik talformatering (t.ex. decimalavgrÀnsare, tusentalsavgrÀnsare). Modulen `locale` tillhandahÄller funktioner för detta.
- **Valutaformatering:** AnvĂ€nd lokalspecifik valutaformatering. ĂvervĂ€g att anvĂ€nda ett bibliotek som `Babel` för mer avancerad valutahantering.
- **Höger-till-vÀnster (RTL)-sprÄk:** Stöd RTL-sprÄk som arabiska och hebreiska. Detta kan innebÀra att man spegelvÀnder layouten pÄ din webbplats.
- **ĂversĂ€ttningskvalitet:** AnvĂ€nd professionella översĂ€ttare för att sĂ€kerstĂ€lla korrekta och kulturellt anpassade översĂ€ttningar. MaskinöversĂ€ttning kan vara en bra utgĂ„ngspunkt, men den krĂ€ver ofta mĂ€nsklig granskning.
- **Detektering av anvÀndarens locale:** Implementera robust detektering av locale baserat pÄ anvÀndarens preferenser, webblÀsarinstÀllningar eller IP-adress. Ge anvÀndarna ett sÀtt att manuellt vÀlja sitt föredragna sprÄk.
- **Testning:** Testa din applikation noggrant med olika locales för att sÀkerstÀlla att allt visas korrekt.
Avancerade Àmnen
Anpassade felsidor:
Du kan anpassa felsidorna som Tornado visar nÀr ett fel uppstÄr. Detta gör att du kan ge en mer anvÀndarvÀnlig upplevelse och inkludera felsökningsinformation.
Anpassade instÀllningar:
Du kan definiera anpassade instÀllningar i din applikationskonfiguration och komma Ät dem i dina request handlers. Detta Àr anvÀndbart för att lagra applikationsspecifika parametrar, sÄsom anslutningsstrÀngar till databaser eller API-nycklar.
Testning:
Testa dina Tornado-applikationer noggrant för att sÀkerstÀlla att de fungerar korrekt och sÀkert. AnvÀnd enhetstester, integrationstester och end-to-end-tester för att tÀcka alla aspekter av din applikation.
Slutsats
Tornado Àr ett kraftfullt och mÄngsidigt webbramverk som Àr vÀl lÀmpat för att bygga skalbara, högpresterande webbapplikationer. Dess asynkrona arkitektur, stöd för WebSockets och lÀttanvÀnda API gör det till ett populÀrt val för utvecklare vÀrlden över. Genom att följa riktlinjerna och exemplen i denna omfattande guide kan du börja bygga dina egna Tornado-applikationer och dra nytta av dess mÄnga funktioner.
Kom ihÄg att konsultera den officiella Tornado-dokumentationen för den mest uppdaterade informationen och bÀsta praxis. Lycka till med kodningen!