Aus Linux-Magazin 01/2006

Python und Twisted zur Netzwerkprogrammierung

© photocase.com

Das Programmieren netzwerkfähiger Anwendungen fällt mit dem Python-Framework Twisted leicht. Von Mail bis zum Chat beherrscht es die wichtigsten Internetprotokolle, auf Wunsch sogar verschlüsselt. Dieser Artikel gibt einen Überblick und demonstriert die Fähigkeiten an einem eigenen Webserver.

Viele Programmierer stehen irgendwann vor der Aufgabe, die Fähigkeit zur Netzwerkkommunikation in ihre Software zu integrieren. Soll sie nur den Inhalt einer Webseite verarbeiten, geht das noch recht einfach. Komplexere Funktionen wie umfassende E-Mail-Fähigkeiten oder ein kompletter Webserver erfordern sehr viel mehr Aufwand.

Obwohl die Python-Standardbibliothek für viele Bereiche des täglichen Programmiererlebens schon passende Module bereitstellt (im Python-Jargon: Batteries included), setzen spezielle Anwendungen externe Pakete voraus. Twisted [1] ist eine gut strukturierte und leistungsfähige Sammlung von Modulen, um Netzwerkfunktionen aller Art in Python-Programme einzuflechten.

Wer etwa einen E-Mail-Client mit Unterstützung diverser Protokolle (POP 3, SMTP, IMAP) schreiben will, dem erleichtert das Twisted-Framework die Arbeit erheblich, da er nicht bei null beginnen muss: Twisted Mail bringt bereits alle wesentlichen Mailprotokolle mit. Neben diesen enthält Twisted auch für SSH, SFTP, HTTP (auch HTTP/1.1), DNS, NNTP und Jabber fertige Module. Wer dennoch das Rad neu erfinden möchte – zum Beispiel bei der Implementierung eigener Protokolle – findet in den Twisted-Modulen »twisted.cred« und »twisted.spread« geeignete Helfer.

Netzwerk asynchron

Grundsätzlich handelt es sich bei Twisted um ein asynchrones Netzwerk-Framework. Im Gegensatz zu anderen Bibliotheken blockieren die entsprechenden Funktionen beim Aufruf also nicht. Eine Anwendung arbeitet einfach weiter, bis sie die Nachricht erhält, dass die gewünschten Daten bereitstehen. Zwar wäre dies auch mit Pythons Standardbibliothek möglich, denn das Modul »asyncore« stellt grundlegende Funktionen zum Umschalten zwischen mehreren I/O-Channels innerhalb eines Thread bereit. Aber Twisted setzt dieses Konzept in seinen Protokollen, Schnittstellen und Komponenten auf einer höheren Ebene um. Damit lassen sich Netzwerkanwendungen programmieren, die auf zusätzliche Prozesse und Threads verzichten und trotzdem mit mehreren I/O-Channels gleichzeitig umgehen.

Sehr modular

Um mit Twisted die eigene Software netzwerkfähig zu machen, muss der Programmierer zunächst herausfinden, welcher Teil des Framework ihm hilft. Die Entwickler haben Twisted beim Übergang von Version 1 zu 2 in mehrere Teilprojekte aufgeteilt, um die Übersichtlichkeit zu erhöhen. Die wichtigsten führt Tabelle 1 auf, eine komplette Liste findet sich unter [2].

Twisted setzt das Modul Zope Interface voraus, das Interfaces implementiert, die im Sprachkern von Python fehlen. Wer nur ein einziges Projekt, zum Beispiel Twisted Web oder Twisted Mail, benutzen möchte, braucht nur das jeweilige Modul von der Projektseite herunterzuladen und zu installieren. Alternativ enthält Twisted Sumo [3] alle (stabilen) Module inklusive Zope Interface.

Die Installation erledigt nach dem Auspacken der Befehl »python setup.py install«. Ist Zope Interface nicht installiert, bricht die Twisted-Installation mit einer Fehlermeldung ab.

Das Modul »twisted.cred« kümmert sich um die Authentifizierung bei der Client-Server-Kommunikation. Es erlaubt vielen Netzwerkprotokollen sich mit einem System zu verbinden, sich ihm gegenüber zu authentifizieren und dann Daten auszutauschen. Zum Beispiel übergibt die Unterstützung von POP 3 in Twisted eine Kombination aus Benutzername und Kennwort, um die angegebene Mailbox für den E-Mail-Account zu öffnen. Wichtig ist hierbei der so genannte Perspective Broker, der den Zugriff auf entfernte Objekte (Remote Objects) bereitstellt und Kopieren, Referenzierung und Caching dieser Objekte implementiert.

Datenbankanbindung

Mit »twisted.enterprise« steht eine Datenbankschnittstelle bereit, die zur Python-DB-API 2.0 kompatibel ist. Der Zugriff auf MySQL-, Oracle oder PostgreSQL-Datenbanken wird damit zum Kinderspiel. Er erfolgt über ein asynchrones Interface, das auch in mehreren Threads laufen kann, ohne dadurch die Thread-Safety im ereignisbasierten Hauptloop von Twisted zu verlieren. Dieser Hauptloop findet sich im Modul »twisted.internet« und heißt »reactor«. Er implementiert die unendliche Schleife (Loop) jedes Programms, in der Twisted verschiedene Ereignisse verarbeitet. Der Reactor stellt die grundlegende Schnittstelle zu wichtigen Twisted-Interna bereit, zum Beispiel Netzwerkverbindungen, Threading oder zur Behandlung von Ereignissen.

Andere Module wie »twisted.protocols« oder »twisted.manhole« werden in der Praxis nur selten benötigt. Conch implementiert für Twisted das Secure-Shell-Protokoll in Version 2. Unter [5] ist eine Anleitung zu finden, die in wenigen Schritten die Umsetzung eines SSH-Clients mit Conch zeigt.

Tabelle 1: Wichtige
Twisted-Module

 

Modul

Funktion

twisted

Framework für asynchrone Anwendungen, es ist die Basis
für alle Teilprojekte von Twisted

twisted.conch

Implementierung der Protokolle SFTP und SSH für Clients
und Server

twisted.web

HTTP-Protokoll für Clients und Server

twisted.web2

Unterstützung für das Protokoll HTTP/1.1 als
Framework für Server; dieses Paket befindet sich zurzeit noch
in Entwicklung und sollte nicht für kritische Anwendungen
eingesetzt werden

twisted.mail

Implementierung der Protokolle SMTP, IMAP und POP für
Clients und Server

twisted.names

Unterstützung für das DNS-Protokoll für Clients
und Server

twisted.news

NNTP-Protokoll für Clients und Server

twisted.words

Module für Chat- oder Instant-Messaging-Anwendungen

Eines der interessantesten Einsatzgebiete von Twisted sind Webserver beziehungsweise Applikationsserver mit Hilfe von »twisted.web« oder »twisted.web2«. Das leistungsfähige Template-Toolkit für diesen Zweck heißt Nevow [6]. Twisted enthält auch alle Funktionen, die zur Programmierung beliebiger HTTP-Clients nötig sind. Das API von »twisted.web« erlaubt mehrere Grade der Abstraktion: Vom einfachen Webserver, über Session-Support und die Verzahnung von Applikationsservern bis zur verteilten Website ist alles möglich.

Wenn ein Webserver eine Anfrage von einem Client erhält, erzeugt er ein Request-Objekt und gibt es an das Resource-System zurück, das die Antwort erzeugt (Abbildung 1).

Neben »twisted.web« gibt es mittlerweile »twisted.web2«, das sich aber noch in der Entwicklungsphase befindet. Die wesentlichen Verbesserungen sind:

  • Unterstützung von HTTP 1.1
  • Eigene und vordefinierte Ausgabefilter, zum Beispiel für
    Gzip-komprimierte Auslieferung von Webseiten
  • Trennung von Low- und Highlevel-Bearbeitung der Anfragen
  • Korrekte Analyse von HTTP-Headern
  • Deutlich verbessertes URL-Rewriting, wenn der Betrieb zusammen
    mit einem Proxy erfolgt

Obwohl die Verbesserungen gegenüber der Vorversion in »twisted.web2« sehr groß sind, warnen die Entwickler derzeit noch vor dem Einsatz – auch weil das Modul zurzeit noch langsamer ist als der Vorgänger.

Als letztes der wichtigen Module ist Twisted Mail anzuführen, das SMTP, POP 3 und IMAP 4 implementiert. Neben den Protokollen beherrscht das Modul auch das Schreiben und Lesen des Mailbox-Formats Maildir. Zusätzlich gibt es eine vorgefertigte Kombination aus SMTP und POP 3 für Mailserver und Virtual-Hosting. Für rückwärtskompatible Anwendungen kann es praktisch sein, dass Twisted Mail einen Großteil der Sendmail-Optionen beherrscht.

Listing 1: Einfacher
Webserver

01 # Module laden
02 from twisted.internet import reactor
03 from twisted.web import static, server
04 
05 # root-Verzeichnis setzen
06 mein_server = static.File('/var/www/htdocs')
07 
08 # Webserver starten auf Port 7777
09 reactor.listenTCP(7777, server.Site(mein_server))
10 reactor.run()

Listing 2: Erweiterter
Webserver

01 # Module laden
02 from twisted.internet import reactor
03 from twisted.web import static, server, twcgi
04 
05 # root-Verzeichnis setzen
06 mein_server = static.File('/var/www/htdocs')
07 
08 # Auswertung von Perl-Skripten
09 class PerlScript(twcgi.FilteredScript):
10         filter = '/usr/bin/perl' # Pfad zum Perl-Interpreter
11 mein_server.processors = {'.pl': PerlScript}
12 
13 # CGI-Verzeichnis einstellen und aktivieren
14 mein_server.putChild('cgis', twcgi.CGIDirectory('/var/www/cgi-bin'))
15 
16 # Verzeichnisse zu anderen Zielen
17 mein_server.putChild('doc', static.File('/var/www/doc'))
18 
19 # Indexdateien
20 mein_server.indexNames = ['index.html', 'index.htm', 'index.pl']
21 
22 # Webserver starten auf Port 7777
23 reactor.listenTCP(7777, server.Site(mein_server))
24 reactor.run()

Eingefrorene Server

Das Twisted-Framework bringt einige Kommandozeilenprogramme mit, die Twisted-Applikationen für spezielle Einsatzbereiche vorbereiten [7]. Die beiden Programme »mktap« und »tapconvert« erstellen aus Python-Quelltext eine Datei im Format Tap, Tas oder Tax, die sich dann mit den unterschiedlichen Twisted-Servern verwenden lässt, zum Beispiel Web, FTP oder IRC.

Leben haucht den toten Applikationen (Tap-Dateien) das Tool »twistd« ein. Streng genommen ist es zum Betrieb von Twisted-Anwendungen nicht notwendig, aber es erleichtert die Arbeit, da es die Kontrolle über den Reactor sowie den Start und die Beendigung der Anwendung übernimmt. Zudem unterstützt »twistd« die Auswahl eines anderen Reactor-Typs, der zum Beispiel den Betrieb als Daemon erlaubt oder auch Logfiles schreibt. Die Programme »tap2deb« und »tap2rpm« packen fertig gestellte Server-Applikationen für die Verteilung in Debian- oder RPM-Pakete ein. Skripte zum Installieren und Entfernen der Server erstellen die Tools automatisch.

Listing 1 zeigt an einem einfachen Webserver, wie leistungsfähig Twisted ist. Solchen Code braucht zum Beispiel, wer seine Anwendung übers Web konfigurierbar machen möchte. Die ersten Zeilen laden die nötigen Module. Zeile 6 erzeugt einen neuen Server mit dem Wurzelverzeichnis für die HTML-Dokumente, hier »/var/www/htdocs«. Die folgende Anweisung teilt dem »reactor« mit, dass er auf Port 7777 nach Anfragen lauschen soll. Der Aufruf »reactor.run()« startet den Webserver.

Listing 2 zeigt einen Webserver, der das Gerüst aus Listing 1 um einige Optionen erweitert. Zunächst aktivieren die Zeilen 9 bis 11 die Unterstützung von Perl-Skripten: Der Server soll Dateien mit der Endung ».pl« an den Perl-Interpreter »/usr/bin/perl« weiterleiten und dessen Ausgabe zurückliefern. An dieser Stelle könnte auch die Unterstützung für PHP und andere Sprachen stehen.

Die Methode »putChild()« in Zeile 14 setzt das CGI-Verzeichnis auf »/var/www/cgi-bin«, was die Skripte unter »http://Servername:7777/cgis« erreichbar macht. Die gleiche Methode legt für das Webverzeichnis »doc« den Ort »/var/www/doc« fest. Die Variable »indexNames« legt fest, nach welchen Dateien der Server bei einer Verzeichnisanfrage sucht. Die Reihenfolge entspricht jener der angegebenen Dateinamen.

Abbildung 1: Der Ablauf einer Webanfrage innerhalb des Twisted-Framework.

Abbildung 1: Der Ablauf einer Webanfrage innerhalb des Twisted-Framework.

Als Alternative zum ausprogrammierten Webserver leisten das Gleiche auch die Twisted-Tools:

mktap web --path /var/www/htdocs --port 7777
twistd --file web.tap

Der Befehl »mktap« erzeugt eine vorkonfigurierte Tap-Datei. In diesem Fall setzt er das Root-Verzeichnis auf »/var/www/htdocs« und den Port auf »7777«. Das Ergebnis landet in der Datei »web.tap«, die dem Serverprogramm »twistd« als Parameter dient. Nach dem Start finden sich im aktuellen Verzeichnis die Logdatei »twistd.log« und das PID-File, das den Server über »kill `cat twistd.pid`« wieder beendet. Weitere Informationen über verfügbare Optionen gibt »mktap web –help«.

Einfach, aber leistungsfähig

Dieser Artikel kann nur einen groben einen Überblick über den Aufbau und die Funktionsweise von Twisted geben. Das Framework dient mit Twisted Mail, Conch, Twisted Web(2) und anderen Teilprojekten als Grundlage für viele Netzwerkanwendungen im professionellen Umfeld – sogar die NASA setzt auf Twisted Matrix [8].

Während Python-Anwendungen damit nach den Sternen greifen können, erleichtert es dem gestressten Programmierer auf Erden auch kleine Arbeiten. Es reduziert deutlich die Zeit, die für die Entwicklung eines Clients oder Servers nötig ist, da es von der Implementierung bekannter Protokolle befreit. Sichere, schnelle, stabile und flexible Netzwerkanwendungen lassen sich auf der Basis von Twisted im Mausumdrehen erstellen, ohne die Möglichkeit für spezielle Erweiterungen zu verlieren. (ofr)

Infos

[1] Projektseite Twisted Matrix: [http://www.twistedmatrix.com]

[2] Übersicht über alle Twisted-Projekte: [http://www.twistedmatrix.com/projects]

[3] Twisted Sumo: [http://twistedmatrix.com/projects/core]

[4] Zope-Interface: [http://www.zope.org/Wikis/Interfaces]

[5] SSH-Client mit Conch: [http://twistedmatrix.com/projects/conch/documentation/howto/conch_client.html]

[6] Nevow (Template-System): [http://divmod.org/projects/nevow]

[7] Tools: [http://twistedmatrix.com/projects/core/documentation/howto/basics.html]

[8] Twisted-Benutzer: [http://twistedmatrix.com/services/success]

Der Autor


Markus Franz berät Unternehmen bei IT-Projekten. Er entwickelt Suchmaschinen für das Internet, unter anderem Metager 2 [www.metager2.de], das vollständig in Python geschrieben ist. Markus Franz ist 17 Jahre alt und Schüler am Armin-Knab-Gymnasium in Kitzingen.

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben