WSGI

Mit Python ist es seit Ewigkeiten möglich, Webanwendungen zu programmieren. Allerdings musste man früher direkt den Webserver ansprechen. Wie diese Kommunikation mit dem Webserver abläuft, hängt vom Interface ab. Bekannte Interfaces sind CGI, FastCGI und mod_python. Auch hat man die Möglichkeit, selber einen Webserver durch Ableiten vom BaseHTTPServer aus der Standardlibrary zu implementieren. Das sind noch nichtmal alle Möglichkeiten.

Aus diesem Grund wurde 2004 das PEP für WSGI (PEP 333) geschrieben, das definiert, wie eine Webanwendung auszusehen hat, um auf jedem Interface zu funktionieren. Da man die Interfaces ja nicht mehr anpassen kann und sie kaum etwas gemein haben, sorgt eine Zwischenschicht (Gateway oder Wrapper genannt) dafür, die Anfragen und Antworten der Webanwendung und des Webservers zu verwalten.

WSGI ist low-level

Wer schon einmal mit PHP programmiert hat, wird sich wundern wie kompliziert WSGI ist. In der Tat ist es denkbar unpraktisch für den täglichen Einsatz. Eine einfache WSGI-Anwendung sieht in etwa so aus:

   1 from cgi import parse_qs, escape
   2 
   3 def app(environ, start_response):
   4     query = parse_qs(environ.get('QUERY_STRING', ''))
   5     start_response('200 OK', [('Content-Type', 'text/html')])
   6     if 'username' in query:
   7         yield 'Dein Name ist %s!' % (escape(query['username'][0]))
   8     else:
   9         yield 'Kein Name angegeben'

Wie hier schon ersichtlich ist, ist eine Anwendung eine Funktion. Das stimmt aber nicht ganz. Eine WSGI Anwendung ist dadurch definiert, dass sie mit den Variablen environ (Webserver Eingabedaten) und start_response (Funktion zum Starten der HTTP Response) initialisiert wird und iterierbar ist. Jede Iteration gibt eine Zeile zurück.

Zur Veranschaulichung:

   1 >>> env = {'QUERY_STRING': 'username=foobar'}
   2 >>> def start_response(code, headers):
   3 ...  print repr(code), headers
   4 ...
   5 >>> appiter = iter(app(env, start_response))
   6 >>> appiter.next()
   7 '200 OK' [('Content-Type', 'text/html')]
   8 'Dein Name ist foobar!'

Im Grunde nicht sehr kompliziert. Diese hier nachvollzogene Programmcode wird sonst vom Gateway ausgeführt. Natürlich um einiges komplexer, aber dieses Beispiel veranschaulicht die Vorgehensweise.

Wie kommt das jetzt zum Webserver?

Das ist jetzt der springende Punkt. Das liegt nämlich alleine in der Hand des Gateways. Da kann man nur in der Doku seines Gateways nachschlagen. Für das mit Python 2.5 eingeführte wsgiref Modul, das einen CGI Handler und einen Standalone Server mitbringt, ist das schnell erklärt:

Standalone

   1 from wsgiref.simple_server import make_server
   2 from yourapplication import app
   3 srv = make_server(host, port)
   4 srv.serve_forever()

CGI

   1 from wsgiref.handlers import CGIHandler
   2 from yourapplication import app
   3 CGIHandler().run(app)

Higher Level Please

Natürlich mag keiner direkt an WSGI basteln. Dafür ist es auch gar nicht gedacht. Es gibt eine Reihe wirklich guter Web-Frameworks, die direkt auf WSGI aufbauen und einem viel Arbeit abnehmen. Wenn es eine komplexere Anwendung wird, kommt man um Paste oder zumindest Pylons nicht herum.

Eine Liste verfügbarer WSGI-Implementierungen, Utilies und Frameworks gibt es im WSGI-Wiki.

Tags: Web | Wsgi

WSGI (last edited 2009-07-03 11:21:06 by BjörnSchulz)