Heim  >  Artikel  >  Backend-Entwicklung  >  Python-Webanwendung: WSGI-Grundlagen

Python-Webanwendung: WSGI-Grundlagen

巴扎黑
巴扎黑Original
2017-03-18 11:44:111106Durchsuche

Dieser Artikel wurde ursprünglich von MaNong.com – Xiao Hao übersetzt. Bitte lesen Sie die Nachdruckanforderungen am Ende des Artikels, um an unserem kostenpflichtigen Beitragsplan teilzunehmen.

Django, Flask, Bottle und allen anderen Python-Webframeworks liegt das Web Server Gateway Interface, kurz WSGI, zugrunde. WSGI ist für Python das, was Servlets für Java sind – eine gemeinsame Spezifikation für Webserver, die es verschiedenen Webservern und Anwendungsframeworks ermöglicht, auf der Grundlage einer gemeinsamen API zu interagieren. Für die meisten Dinge ist die Python-Version jedoch recht einfach zu implementieren.

WSGI ist im PEP 3333-Protokoll definiert. Wenn Sie nach der Lektüre dieses Artikels mehr erfahren möchten, empfiehlt der Autor den Lesern, zuerst die Einleitung zu lesen.

Dieser Artikel stellt Ihnen WSGI-Anweisungen aus der Sicht eines Anwendungsentwicklers vor und zeigt Ihnen, wie Sie Anwendungen direkt über WSGI entwickeln (falls Sie es nicht erwarten können).

Ihre erste WSGI-Anwendung

Hier ist die einfachste Python-Webanwendung:

def app(environ, start_fn):
    start_fn('200 OK', [('Content-Type', 'text/plain')])
    return ["Hello World!\n"]

Das ist es! die gesamte Datei. Nennen Sie es app.py und führen Sie es auf einem beliebigen WSGI-kompilierbaren Server aus. Sie erhalten ein Hello World mit einem Antwortstatuscode von 200. Dazu können Sie gunicorn verwenden, gunicorn app:app über pip (pip install gunicorn) installieren und ausführen. Dieser Befehl weist Gunicorn an, den WSGI-Aufruf aus den Anwendungsvariablen im Anwendungsmodul abzurufen.

Ich war gerade sehr aufgeregt. Können Sie eine Anwendung mit nur drei Codezeilen ausführen? Das muss in gewisser Weise eine Protokollierung sein (ausgenommen PHP, da mod_php im Spiel ist). Ich wette, Sie möchten jetzt mehr darüber erfahren.

Was ist also der wichtigste Teil einer WSGI-Anwendung?

  • Eine WSGI-Anwendung ist eine aufrufbare Python-Anwendung, wie eine Funktion, eine Klasse oder eine Klasseninstanz mit einer __call__-Methode

  • Eine aufrufbare Anwendung muss zwei Argumente akzeptieren: environ, ein Python-Wörterbuch, das die erforderlichen Daten enthält, und start_fn, das selbst aufrufbar ist.

  • Die Anwendung muss start_fn mit zwei Parametern aufrufen können: dem Statuscode (String) und einer Liste, die durch einen Header aus zwei Tupeln dargestellt wird.

  • Die Anwendung gibt ein praktisches iterierbares Objekt zurück, das Bytes im Rückgabetext enthält, den Streaming-Teil – der beispielsweise jeweils nur die Zeichenfolgenliste „Hello, World!“ enthält. (Wenn app eine Klasse ist, kann dies in der __iter__-Methode erfolgen)

Zum Beispiel sind die folgenden beiden Beispiele äquivalent zum ersten:

class app(object):

    def __init__(self, environ, start_fn):
        self.environ = environ
        self.start_fn = start_fn

    def __iter__(self):
        self.start_fn('200 OK', [('Content-Type', 'text/plain')])
        yield "Hello World!\n"
class Application(object):
    def __call__(self, environ, start_fn):
        start_fn('200 OK', [('Content-Type', 'text/plain')])
        yield "Hello World!\n"

app = Application()

Sie haben vielleicht angefangen, darüber nachzudenken, wofür Sie diese Dinge verwenden können, aber das Wichtigste ist, Middleware zu schreiben.

Aktivieren

Middleware ist eine praktische Möglichkeit, die Funktionalität von WSGI-Anwendungen zu erweitern. Da Sie nur ein aufrufbares Objekt bereitstellen müssen, können Sie es in jede andere Funktion einschließen.

Angenommen, wir möchten den Inhalt der Umgebung erkennen. Wir können ganz einfach eine Middleware erstellen, um dies wie folgt zu erreichen:

import pprint

def handler(environ, start_fn):
    start_fn('200 OK', [('Content-Type', 'text/plain')])
    return ["Hello World!\n"]

def log_environ(handler):
    def _inner(environ, start_fn):
        pprint.pprint(environ)
        return handler(environ, start_fn)
    return _inner

app = log_environ(handler)

Hier ist log_environ eine Funktion, die eine Funktion im Parameter environ zurückgibt. Dekorieren Sie diesen Parameter bevor der ursprüngliche Rückruf verzögert wird.

Der Vorteil des Schreibens von Middleware auf diese Weise besteht darin, dass die Middleware und der Prozessor sich nicht kennen oder sich umeinander kümmern müssen. Sie können log_environ beispielsweise problemlos an eine Flask-Anwendung binden, da es sich bei der Flask-Anwendung um eine WSGI-Anwendung handelt.

Einige andere nützliche Middleware-Designs:

import pprint

def handle_error(handler):
    def _inner(environ, start_fn):
        try:
            return handler(environ, start_fn)
        except Exception as e:
            print e  # Log error
            start_fn('500 Server Error', [('Content-Type', 'text/plain')])
            return ['500 Server Error']
    return _inner

def wrap_query_params(handler):
    def _inner(environ, start_fn):
        qs = environ.get('QUERY_STRING')
        environ['QUERY_PARAMS'] = urlparse.parse_qs(qs)
        return handler(environ, start_fn)
    return _inner

Wenn Sie nicht möchten, dass Ihre Datei eine große Pyramidenbasis hat, können Sie Reduzieren einmal auf mehrere anwenden Middleware.

# Applied from bottom to top on the way in, then top to bottom on the way out
MIDDLEWARES = [wrap_query_params,
               log_environ,
               handle_error]

app = reduce(lambda h, m: m(h), MIDDLEWARES, handler)

Mit den Vorteilen des Parameters start_fn können Sie auch Middleware schreiben, die den Antworttext dekoriert. Unten finden Sie eine Middleware, deren Inhaltstyp-Header text/plain ist, um das Ausgabeergebnis umzukehren.

def reverser(handler):

    # A reverse function
    rev = lambda it: it[::-1]

    def _inner(environ, start_fn):
        do_reverse = []  # Must be a reference type such as a list

        # Override start_fn to check the content type and set a flag
        def start_reverser(status, headers):
            for name, value in headers:
                if (name.lower() == 'content-type'
                        and value.lower() == 'text/plain'):
                    do_reverse.append(True)
                    break

            # Remember to call `start_fn`
            start_fn(status, headers)

        response = handler(environ, start_reverser)

        try:
            if do_reverse:
                return list(rev(map(rev, response)))

            return response
        finally:
            if hasattr(response, 'close'):
                response.close()
    return _inner

Aufgrund der Trennung von start_fn und dem Antworttext ist es etwas verwirrend, aber es funktioniert trotzdem perfekt.

Bitte beachten Sie außerdem, dass wir zur strikten Einhaltung der WSGI-Spezifikation die Methode close im Antworttext überprüfen und aufrufen müssen, falls vorhanden. Es ist möglich, dass eine WSGI-Anwendung eine write-Funktion anstelle eines iterierbaren Objekts zurückgibt, das den Handler aufruft, und Sie müssen sich möglicherweise damit befassen, wenn Sie möchten, dass Ihre Middleware ältere Anwendungen unterstützt.

Sobald Sie ein wenig mit nativem WSGI herumspielen, beginnen Sie zu verstehen, warum Python über eine Reihe von Web-Frameworks verfügt. WSGI macht es sehr einfach, etwas von Grund auf aufzubauen. Beispielsweise denken Sie möglicherweise über das folgende Routing-Problem nach:

routes = {
    '/': home_handler,
    '/about': about_handler,
}

class Application(object):
    def __init__(self, routes):
        self.routes = routes

    def not_found(self, environ, start_fn):
        start_fn('404 Not Found', [('Content-Type', 'text/plain')])
        return ['404 Not Found']

    def __call__(self, environ, start_fn):
        handler = self.routes.get(environ.get('PATH_INFO')) or self.not_found
        return handler(environ, start_fn)

Wenn Ihnen die Flexibilität der folgenden Ressourcensammlung gefällt, ist es sehr praktisch, WSGI direkt zum Erstellen des Rads zu verwenden.

  • Vorlagenbibliothek: Fügen Sie eine beliebige Vorlage ein (z. B. Jinja2, Pystashe) und geben Sie die gerenderte Vorlage von Ihrem Prozessor zurück!

  • Verwenden Sie eine Bibliothek, die Ihnen beim Routing hilft, z. B. Routen oder Werkzeug-Routing. Wenn Sie WSGI einfach nutzen möchten, werfen Sie einen Blick auf Werkzeug.

  • Verwenden Sie eine beliebige Flask- oder ähnliche Datenbankmigrationsbibliothek.

Natürlich kann es für nicht-professionelle Anwendungen auch sinnvoll sein, ein Framework zu verwenden, damit auch einige spezielle Beispiele wie dieses sinnvoll gelöst werden können.

Was ist mit dem Server?

Es gibt viele Möglichkeiten, WSGI-Anwendungen bereitzustellen. Wir haben bereits über Gunicorn gesprochen, eine ziemlich gute Wahl. uWSGI ist eine weitere gute Wahl. Stellen Sie jedoch sicher, dass Sie Dinge wie Nginx einrichten, bevor Sie diese statischen Dinge bereitstellen, und Sie sollten einen festen Startknoten haben.

Das obige ist der detaillierte Inhalt vonPython-Webanwendung: WSGI-Grundlagen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:Erste Einführung in PythonNächster Artikel:Erste Einführung in Python