Heim  >  Artikel  >  Backend-Entwicklung  >  Sie müssen verstehen, was WSGI ist

Sie müssen verstehen, was WSGI ist

coldplay.xixi
coldplay.xixinach vorne
2020-11-10 17:01:041932Durchsuche

Die Kolumne „Python-Video-Tutorial“ stellt WSGI vor.

Ich schreibe seit mehreren Jahren Python-Web, aber ich weiß immer noch nicht, was WSGI ist und ob es viele Leute da draußen gibt. Das ist normal, denn als Entwickler müssen Sie selten verstehen, was wsgi ist, um eine Website zu erstellen. Sie müssen verstehen, was WSGI ist

Aber wenn Sie selbst ein Webframework schreiben möchten, müssen Sie wsgi verstehen.

Zur Überprüfung: Wenn wir Python für die Webentwicklung verwenden, entwickeln wir normalerweise auf der Grundlage eines bestimmten Web-Frameworks wie Django oder Flask und anderen Frameworks. Nachdem die Geschäftsentwicklung abgeschlossen ist, muss sie auf einem Server bereitgestellt werden, um externen Zugriff zu ermöglichen.

Wenn Sie zu diesem Zeitpunkt online suchen, werden Sie darauf hingewiesen, dass Sie für die Bereitstellung Gunicorn oder UWSGI verwenden müssen. Was sind Gunicorn und Uwsgi?

Sie werden es verstehen, wenn Sie sich dieses Bild ansehen.

Die Rolle, die uwsgi oder gunicorn hier spielt, ist ein Server auf Softwareebene wird verwendet, um Browser zu verarbeiten. Die gesendete HTTP-Anfrage und das Antwortergebnis werden an das Frontend zurückgegeben. Die Hauptaufgabe des Web-Frameworks besteht darin, Geschäftslogik zu verarbeiten und Ergebnisse an den Webserver zu generieren, und der Webserver gibt sie dann an den Browser zurück.

Die Kommunikation zwischen dem Webframework und dem Webserver muss einer Reihe von Spezifikationen folgen, und diese Spezifikation ist WSGI.

Warum müssen wir ein solches Regelwerk erlassen? Standards sollen Standards vereinheitlichen und die Nutzung für alle erleichtern. Stellen Sie sich vor, dass unsere Mobiltelefon-Ladeschnittstellen jetzt Typ-C-Standards sind. Mobiltelefonhersteller produzieren Mobiltelefone gemäß dieser Spezifikation, und Ladegerätehersteller folgen Typ-C. Ladegeräte werden nach den Spezifikationen von c hergestellt und Mobiltelefone verschiedener Hersteller können mit Ladegeräten verschiedener Hersteller verwendet werden. Allerdings gibt es bei Apple eigene Vorschriften, die letztendlich dazu führen, dass das Android-Ladegerät Apple nicht aufladen kann.

![

](p9-juejin.byteimg.com/tos-cn-i-k3…)

Wie schreibt man also ein Anwendungsprogramm (Framework) und einen Server, der der WSGI-Spezifikation entspricht?

Wie im Bild oben gezeigt, ist links der Webserver und rechts das Webframework bzw. die Webanwendung.

Application

WSGI legt fest, dass die Anwendung ein aufrufbares Objekt sein muss (das aufrufbare Objekt kann eine Funktion, eine Klasse oder ein Instanzobjekt sein, das

implementiert) und zwei Parameter akzeptieren muss. Der Rückgabewert des Objekts muss ein sein iterierbares Objekt.

Wir können das einfachste Anwendungsbeispiel schreiben

HELLO_WORLD = b"Hello world!\n"def application(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-type', 'text/plain')]
    start_response(status, response_headers)    return [HELLO_WORLD]复制代码

Anwendung ist eine Funktion, die ein aufrufbares Objekt sein muss und dann zwei Parameter empfängt: environ und start_response__call__

environ ist ein Wörterbuch. Es speichert alle Inhalte im Zusammenhang mit HTTP-Anforderungen, wie Header, Anforderungsparameter usw.

start_response ist eine vom WSGI-Server übergebene Funktion, mit der der Antwortheader und der Statuscode an den Server übergeben werden.

  • Der Aufruf der Funktion start_response ist für die Übergabe des Antwortheaders und des Statuscodes an den Server verantwortlich. Der Antworttext wird von der Anwendungsfunktion an den Server zurückgegeben. Eine vollständige HTTP-Antwort wird von diesen beiden Funktionen bereitgestellt.
  • Jedes Webframework, das wsgi implementiert, verfügt über ein solches aufrufbares Objekt
Server

WSGI. Der Server empfängt jedes Mal eine HTTP-Anfrage, erstellt das Umgebungsobjekt, ruft dann das Anwendungsobjekt auf und gibt schließlich die HTTP-Antwort zurück zum Browser.

Das Folgende ist der Code eines vollständigen WSGI-Servers

import socketimport sysfrom io import StringIOclass WSGIServer(object):
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    request_queue_size = 1

    def __init__(self, server_address):
        # Create a listening socket
        self.listen_socket = listen_socket = socket.socket(
            self.address_family,
            self.socket_type
        )        # Allow to reuse the same address
        listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)        # Bind
        listen_socket.bind(server_address)        # Activate
        listen_socket.listen(self.request_queue_size)        # Get server host name and port
        host, port = self.listen_socket.getsockname()[:2]
        self.server_name = socket.getfqdn(host)
        self.server_port = port        # Return headers set by Web framework/Web application
        self.headers_set = []    def set_app(self, application):
        self.application = application    def serve_forever(self):
        listen_socket = self.listen_socket        while True:            # New client connection
            self.client_connection, client_address = listen_socket.accept()            # Handle one request and close the client connection. Then
            # loop over to wait for another client connection
            self.handle_one_request()    def handle_one_request(self):
        self.request_data = request_data = self.client_connection.recv(1024)        # Print formatted request data a la 'curl -v'
        print(''.join(            '< {line}\n&#39;.format(line=line)            for line in request_data.splitlines()
        ))
        self.parse_request(request_data)        # Construct environment dictionary using request data
        env = self.get_environ()        # It&#39;s time to call our application callable and get
        # back a result that will become HTTP response body
        result = self.application(env, self.start_response)        # Construct a response and send it back to the client
        self.finish_response(result)    def parse_request(self, text):
        request_line = text.splitlines()[0]
        request_line = request_line.rstrip(&#39;\r\n&#39;)        # Break down the request line into components
        (self.request_method,  # GET
         self.path,  # /hello
         self.request_version  # HTTP/1.1
         ) = request_line.split()    def get_environ(self):
        env = {}        # The following code snippet does not follow PEP8 conventions
        # but it&#39;s formatted the way it is for demonstration purposes
        # to emphasize the required variables and their values
        #
        # Required WSGI variables
        env[&#39;wsgi.version&#39;] = (1, 0)
        env[&#39;wsgi.url_scheme&#39;] = &#39;http&#39;
        env[&#39;wsgi.input&#39;] = StringIO.StringIO(self.request_data)
        env[&#39;wsgi.errors&#39;] = sys.stderr
        env[&#39;wsgi.multithread&#39;] = False
        env[&#39;wsgi.multiprocess&#39;] = False
        env[&#39;wsgi.run_once&#39;] = False
        # Required CGI variables
        env[&#39;REQUEST_METHOD&#39;] = self.request_method  # GET
        env[&#39;PATH_INFO&#39;] = self.path  # /hello
        env[&#39;SERVER_NAME&#39;] = self.server_name  # localhost
        env[&#39;SERVER_PORT&#39;] = str(self.server_port)  # 8888
        return env    def start_response(self, status, response_headers, exc_info=None):
        # Add necessary server headers
        server_headers = [
            (&#39;Date&#39;, &#39;Tue, 31 Mar 2015 12:54:48 GMT&#39;),
            (&#39;Server&#39;, &#39;WSGIServer 0.2&#39;),
        ]
        self.headers_set = [status, response_headers + server_headers]        # To adhere to WSGI specification the start_response must return
        # a &#39;write&#39; callable. We simplicity&#39;s sake we&#39;ll ignore that detail
        # for now.
        # return self.finish_response

    def finish_response(self, result):
        try:
            status, response_headers = self.headers_set
            response = &#39;HTTP/1.1 {status}\r\n&#39;.format(status=status)            for header in response_headers:
                response += &#39;{0}: {1}\r\n&#39;.format(*header)
            response += &#39;\r\n&#39;
            for data in result:
                response += data            # Print formatted response data a la &#39;curl -v&#39;
            print(&#39;&#39;.join(                &#39;> {line}\n'.format(line=line)                for line in response.splitlines()
            ))
            self.client_connection.sendall(response)        finally:
            self.client_connection.close()


SERVER_ADDRESS = (HOST, PORT) = 'localhost', 8080def make_server(server_address, application):
    server = WSGIServer(server_address)
    server.set_app(application)    return serverif __name__ == '__main__':
    httpd = make_server(SERVER_ADDRESS, application)
    print('WSGIServer: Serving HTTP on port {port} ...\n'.format(port=PORT))
    httpd.serve_forever()复制代码

Wenn Sie nur einen Server für die Entwicklungsumgebung schreiben, müssen Sie sich natürlich nicht die Mühe machen, das Rad selbst neu zu erfinden, da Python integriert ist Das Modul stellt die Funktion eines WSGI-Servers bereit.

from wsgiref.simple_server import make_server
srv = make_server('localhost', 8080, application)
srv.serve_forever()复制代码
Nur 3 Zeilen Code können einen WSGI-Server bereitstellen. Lassen Sie uns abschließend die Wirkung des Browsers testen, der eine Anfrage initiiert. Das Obige ist eine Einführung in WSGI Wenn Sie ein tieferes Verständnis von wsgi haben, können Sie sich mit PEP333 vertraut machen

Verwandte kostenlose Lernempfehlungen:

Python-Video-Tutorial

Das obige ist der detaillierte Inhalt vonSie müssen verstehen, was WSGI ist. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.im. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen