Wie Python-Webframeworks, WSGI und CGI zusammenpassen

150

Ich habe ein Bluehost- Konto, in dem ich Python-Skripte als CGI ausführen kann. Ich denke, es ist das einfachste CGI, denn um es auszuführen, muss ich Folgendes definieren in .htaccess:

Options +ExecCGI
AddType text/html py
AddHandler cgi-script .py

Wenn ich jetzt mit Python nach Webprogrammierung suche, höre ich viel über WSGI und wie die meisten Frameworks es verwenden. Aber ich verstehe einfach nicht, wie alles zusammen passt, besonders wenn mein Webserver gegeben ist (Apache läuft auf dem Computer eines Hosts) und nicht etwas, mit dem ich wirklich spielen kann (außer .htaccessBefehle definieren ).

Wie sind WSGI , CGI und die Frameworks miteinander verbunden? Was muss ich wissen, installieren und tun, wenn ich ein Webframework (z. B. web.py oder CherryPy ) für meine grundlegende CGI-Konfiguration ausführen möchte ? Wie installiere ich die WSGI-Unterstützung?

Eli Bendersky
quelle

Antworten:

242

Wie sind WSGI, CGI und die Frameworks miteinander verbunden?

Apache überwacht Port 80. Es wird eine HTTP-Anfrage gesendet. Es analysiert die Anfrage, um einen Weg zu finden, um zu antworten. Apache hat eine Menge Auswahlmöglichkeiten. Eine Möglichkeit zu antworten besteht darin, CGI zum Ausführen eines Skripts zu verwenden. Eine andere Möglichkeit zu antworten besteht darin, einfach eine Datei bereitzustellen.

Im Fall von CGI bereitet Apache eine Umgebung vor und ruft das Skript über das CGI-Protokoll auf. Dies ist eine Standard-Unix Fork / Exec-Situation. Der CGI-Unterprozess erbt eine Betriebssystemumgebung, einschließlich Socket und Standardausgabe. Der CGI-Unterprozess schreibt eine Antwort, die auf Apache zurückgeht. Apache sendet diese Antwort an den Browser.

CGI ist primitiv und nervig. Meistens, weil für jede Anforderung ein Unterprozess gegabelt wird und der Unterprozess stdout und stderr beenden oder schließen muss, um das Ende der Antwort anzuzeigen.

WSGI ist eine Schnittstelle, die auf dem CGI-Entwurfsmuster basiert. Es ist nicht unbedingt CGI - es muss nicht für jede Anforderung ein Unterprozess gegabelt werden. Es kann CGI sein, muss es aber nicht sein.

WSGI ergänzt das CGI-Entwurfsmuster auf mehrere wichtige Arten. Es analysiert die HTTP-Anforderungsheader für Sie und fügt diese der Umgebung hinzu. Es liefert jede POST-orientierte Eingabe als dateiähnliches Objekt in der Umgebung. Es bietet Ihnen auch eine Funktion, die die Antwort formuliert und Sie vor vielen Formatierungsdetails bewahrt.

Was muss ich wissen / installieren / tun, wenn ich ein Webframework (z. B. web.py oder cherrypy) für meine grundlegende CGI-Konfiguration ausführen möchte?

Denken Sie daran, dass das Gabeln eines Teilprozesses teuer ist. Es gibt zwei Möglichkeiten, dies zu umgehen.

  1. Eingebettet mod_wsgi oder mod_pythonbettet Python innerhalb Apache; Es ist kein Prozess gegabelt. Apache führt die Django-Anwendung direkt aus.

  2. Daemon mod_wsgi oder mod_fastcgiermöglicht Apache die Interaktion mit einem separaten Daemon (oder "lang laufenden Prozess") unter Verwendung des WSGI-Protokolls. Sie starten Ihren lang laufenden Django-Prozess und konfigurieren dann mod_fastcgi von Apache für die Kommunikation mit diesem Prozess.

Beachten Sie, dass mod_wsgidies in beiden Modi funktionieren kann: Embedded oder Daemon.

Wenn Sie sich über mod_fastcgi informieren, werden Sie feststellen, dass Django aus flup eine WSGI-kompatible Schnittstelle aus den von mod_fastcgi bereitgestellten Informationen erstellt. Die Pipeline funktioniert so.

Apache -> mod_fastcgi -> FLUP (via FastCGI protocol) -> Django (via WSGI protocol)

Django hat mehrere "django.core.handlers" für die verschiedenen Schnittstellen.

Für mod_fastcgi bietet Django eine manage.py runfcgi, die FLUP und den Handler integriert.

Für mod_wsgi gibt es dafür einen Core-Handler.

Wie installiere ich die WSGI-Unterstützung?

Befolgen Sie diese Anweisungen.

https://code.google.com/archive/p/modwsgi/wikis/IntegrationWithDjango.wiki

Hintergrundinformationen finden Sie hier

http://docs.djangoproject.com/de/dev/howto/deployment/#howto-deployment-index

S.Lott
quelle
4
Ich kann mod_wsgi nicht installieren, da ich auf Shared Hosting bin. Alles was ich habe ist fcgi Unterstützung. Wie kann ich trotzdem WSGI-Apps ausführen?
Eli Bendersky
3
+1 Das ist eine ausgezeichnete Antwort und beantwortet viele (aber nicht alle) Fragen, an die ich gedacht habe. Diese Antwort ist immer noch nicht vollständig. Sie haben CGI & WSGI gut erklärt, aber wie ist die Beziehung und die Unterschiede zwischen FASTCGI & WSGI? Welches ist besser? Wie arbeiten Sie? Wie kam mod_python ins Bild?
Krallen
14
S.Lott, anstatt sich zu beschweren, wenn Leute fragen, was "besser" ist, warum nicht einfach sagen "mod_wsgi ist besser als X, fastcgi ist besser für Y", und wenn das OP spezifischere Fragen hat, werden sie fragen.
Gregg Lind
7
@ Greg Lind: Warum nicht einfach sagen "mod_wsgi ist besser als X, fastcgi ist besser für Y"? Weil es nicht sehr einfach ist. Es gibt Dutzende nicht funktionaler Qualitätsfaktoren, die Elemente der X- und Y-Mengen sind. Es ist schwierig, sie alle aufzuzählen. Es ist weitaus besser für Leute, spezifische Fragen zu den relevanten Qualitätsfaktoren zu stellen.
S.Lott
4
Nur für die Hinweise: Die Option runfcgi ist veraltet, da Version 1.7 und FastCGI-Unterstützung in Django 1.9 entfernt wurden.
OBu
58

Ich denke, Florians Antwort beantwortet den Teil Ihrer Frage zu "Was ist WSGI?", Insbesondere wenn Sie das PEP lesen .

Was die Fragen betrifft, die Sie gegen Ende stellen:

WSGI, CGI, FastCGI usw. sind Protokolle, mit denen ein Webserver Code ausführen und den erzeugten dynamischen Inhalt bereitstellen kann. Vergleichen Sie dies mit dem statischen Web-Serving, bei dem eine einfache HTML-Datei grundsätzlich so wie sie ist an den Client geliefert wird.

CGI, FastCGI und SCGI sind sprachunabhängig. Sie können CGI-Skripte in Perl, Python, C, Bash usw. schreiben. CGI definiert, welche ausführbare Datei basierend auf der URL aufgerufen wird und wie sie aufgerufen wird: die Argumente und die Umgebung. Außerdem wird definiert, wie der Rückgabewert nach Abschluss Ihrer ausführbaren Datei an den Webserver zurückgegeben werden soll. Die Variationen sind im Grunde genommen Optimierungen, um mehr Anforderungen bearbeiten, die Latenz reduzieren und so weiter zu können. Das Grundkonzept ist das gleiche.

WSGI ist nur Python. Anstelle eines sprachunabhängigen Protokolls wird eine Standardfunktionssignatur definiert:

def simple_app(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!\n']

Dies ist eine vollständige (wenn auch eingeschränkte) WSGI-Anwendung. Ein Webserver mit WSGI-Unterstützung (z. B. Apache mit mod_wsgi) kann diese Funktion aufrufen, wenn eine Anforderung eingeht.

Der Grund dafür ist, dass wir den chaotischen Schritt vermeiden können, von einem HTTP-GET / POST zu CGI zu Python und wieder zurück auf dem Weg nach draußen zu konvertieren. Es ist eine viel direktere, sauberere und effizientere Verknüpfung.

Es macht es auch viel einfacher, lang laufende Frameworks hinter Webservern laufen zu lassen, wenn für eine Anfrage nur ein Funktionsaufruf erforderlich ist. Mit einfachem CGI müssten Sie Ihr gesamtes Framework für jede einzelne Anforderung starten .

Um WSGI-Unterstützung zu erhalten, müssen Sie ein WSGI-Modul (wie mod_wsgi ) installiert oder einen Webserver mit integriertem WSGI (wie CherryPy ) verwenden. Wenn keiner von denen sind möglich, Sie könnten die CGI-WSGI - Brücke in dem PEP gegeben verwenden.

James Brady
quelle
3
Wessen dumme Idee war es, die WSGI-Sprache nicht agnostisch zu machen? Was ist der Sinn dann? Könnte auch einfach ganz Python als Apache-Modul ausliefern.
Salman von Abbas
2
@ SalmanPK Ich denke, es ist nur ein Kompromiss. Sicherlich ist es nicht einfach (wenn nicht unmöglich), ein sprachunabhängiges Protokoll zu erstellen, das durch einfaches Implementieren einer Funktion in der ausgewählten Sprache verwendet werden kann.
Phunehehe
21

Sie können WSGI über CGI ausführen, wie Pep333 als Beispiel zeigt. Jedes Mal, wenn eine Anforderung vorliegt, wird ein neuer Python-Interpreter gestartet und der gesamte Kontext (Datenbankverbindungen usw.) muss erstellt werden, was alle Zeit in Anspruch nimmt.

Wenn Sie WSGI ausführen möchten, ist es am besten, wenn Ihr Host mod_wsgi installiert und eine geeignete Konfiguration vornimmt, um die Steuerung auf eine Ihrer Anwendungen zu verschieben.

Flup ist eine weitere Möglichkeit, mit WSGI für jeden Webserver zu arbeiten, der FCGI , SCGI oder AJP sprechen kann . Nach meiner Erfahrung funktioniert nur FCGI wirklich und kann in Apache entweder über mod_fastcgi oder wenn Sie einen separaten Python-Daemon mit mod_proxy_fcgi ausführen können .

WSGI ist ein Protokoll ähnlich wie CGI, das eine Reihe von Regeln definiert, wie Webserver und Python-Code interagieren können. Es wird als Pep333 definiert . Es ist möglich, dass viele verschiedene Webserver viele verschiedene Frameworks und Anwendungen verwenden können, die dasselbe Anwendungsprotokoll verwenden. Dies ist sehr vorteilhaft und macht es so nützlich.

Florian Bösch
quelle
3
Wird WSGI über CGI ausgeführt, wofür "flup" gedacht ist? Wie ist flup mit dem Schema verbunden?
Eli Bendersky
7

Wenn Sie sich über alle Begriffe in diesem Bereich nicht sicher sind und es sich um einen verwirrenden, mit Akronymen beladenen handelt, gibt es auch einen guten Hintergrundleser in Form eines offiziellen Python-HOWTO, in dem CGI vs. FastCGI vs. WSGI und so weiter diskutiert wird unter: http://docs.python.org/howto/webservers.html

Richard Boardman
quelle
2
URL ist veraltet, ich denke, dies ist eine aktualisierte: docs.python.org/2.7/howto/webservers.html
Stefaan
Tolles Material :) Man sollte diese offizielle Einführung zusammen mit der akzeptierten Antwort lesen.
Rick
4

Es ist eine einfache Abstraktionsschicht für Python, ähnlich der Servlet-Spezifikation für Java. Während CGI sehr niedrig ist und nur Daten in die Prozessumgebung und den Standard-Ein- / Ausgang speichert, modellieren die beiden oben genannten Spezifikationen die http-Anforderung und -Antwort als Konstrukte in der Sprache. Mein Eindruck ist jedoch, dass sich die Leute in Python nicht ganz auf De-facto-Implementierungen festgelegt haben, sodass Sie eine Mischung aus Referenzimplementierungen und anderen Bibliotheken vom Typ Dienstprogramm haben, die neben der WSGI-Unterstützung auch andere Dinge bieten (z. B. Einfügen). Natürlich könnte ich mich irren, ich bin ein Neuling in Python. Die "Web Scripting" Community kommt aus einer anderen Richtung auf das Problem zu (Shared Hosting, CGI Legacy,

Aaron
quelle