0%

Kapitel 6 · Übung

Die Bibliothek websockets, ohne asyncio

websockets installieren und festlegen

Dein Echo-Dienst aus Kapitel 5 funktioniert: Der handgebaute Client und der handgebaute Server stimmen bei jedem überein. Diese Übereinstimmung beweist weniger, als es scheint. Beide Seiten stammen aus denselben , 618 Zeilen in ws_handshake.py, ws_frames.py und loopback_demo.py, und ein Fehler, der auf beiden Seiten auf dieselbe Weise gemacht wird, hebt sich auf, so wie es eine 16-Bit-Länge getan hätte, die in Kapitel 3 von beiden geschrieben worden wäre. Um einen solchen Fehler zu finden, muss etwas, das andere Leute geschrieben haben, mit deinem Server reden.

Dieses Kapitel bringt die Bibliothek websockets ins Spiel, von anderen Leuten nach demselben RFC 6455 geschrieben. Zuerst testet sie deinen Code; ab Lektion 2 übernimmt sie die Infrastruktur.

Der Projektbaum enthält die fertigen Versionen des Kurses von loopback_demo.py, ws_frames.py und ws_handshake.py, sodass das Kapitel von bekannten Dateien ausgeht, egal wie dein eigener Code aus Kapitel 5 aussah; nichts in diesem Kapitel ändert sie. Ab Lektion 2 schreibst du echo_library.py, und Run startet in den Editor-Lektionen library_demo.py.

Welche Version hier ist

Diese Lektion hat ein , und ihre Sandbox kann außer sich selbst genau eine Sache erreichen: den Paketspiegel des Kurses, denselben internen , aus dem Python in der Praxis installiert hat. Nichts im öffentlichen Internet ist erreichbar. Frag zuerst das eigene Python der Sandbox, welche Version der Bibliothek es mitbringt:

python -c "import websockets; print(websockets.__version__)"

Es sollte 17.4 ausgeben, die Version, mit der dieser Kurs geprüft wurde und die die Sandbox der Website hat. Diese Kopie ist für das Python der Sandbox installiert, also kann jede spätere Lektion import websockets ausführen, ohne etwas zu installieren.

Festlegen

requirements.txt enthält bereits eine Zeile, pytest==9.1.1. Öffne die Datei im Tab Project oder wie in Python in der Praxis mit nano requirements.txt in der Shell und füge die Bibliothek darunter hinzu, sodass die Datei so lautet:

pytest==9.1.1
websockets==17.4

Das == legt die genaue Version fest. Bibliotheken ändern sich zwischen Releases: Einige , die dieses Kapitel übergibt, gibt es in älteren Versionen dieser Bibliothek nicht. Auf deinem eigenen Computer gibt dir pip install -r requirements.txt dann die Bibliothek, die dieses Kapitel verwendet.

Warum websockets==17.4 schreiben statt websockets?

Sichtbar installieren

Beweise jetzt, dass die Datei genügt, um die Umgebung neu aufzubauen. Erstelle eine neue , installiere aus der Datei und auf, was die Umgebung enthält:

python -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
echo $?
.venv/bin/python -m pip freeze

pip liest beide Zeilen und installiert aus dem Paketspiegel des Kurses, und echo $? gibt seinen Exit-Code aus, 0, wenn die Installation funktioniert hat. Auf der Website war der Status 0, und pip freeze hat pytest und die Pakete, die pytest braucht, aufgelistet, und die Zeile websockets==17.4. Frag dann die neue Umgebung, welche Version sie bekommen hat:

.venv/bin/python -c "import websockets; print(websockets.__version__)"

Lokal hat es 17.4 ausgegeben, dieselbe Version, die das eigene Python der Sandbox melden sollte.

Wenn die Installation stattdessen scheitert, gibt pip einen Fehler aus, echo $? gibt einen anderen Status als 0 aus, und pip freeze zeigt keine -Zeile. Das liegt an der Verbindung der Sandbox zum Paketspiegel, nicht an deiner Datei: Deine Festlegung ist weiterhin das, was die Prüfung liest, und keine spätere Lektion verwendet diese Installation.

Die Website speichert .venv nie. Erzeugte Verzeichnisse werden beim Speichern deines Projekts ausgelassen, wie Python in der Praxis gezeigt hat, also ist die Umgebung, die du gerade gebaut hast, in der nächsten Lektion weg. Spätere Lektionen verwenden die Kopie, die für das Python der Sandbox installiert ist, und das ist dieselbe Version. Die Festlegung ist für deinen eigenen Rechner und für jeden, der dieses Projekt nach dir installiert.

Du öffnest die nächste Lektion. Ist dein .venv noch da?

Die Bibliothek trifft deinen Server

Öffne interop.py und lies es; jedes Warten darin ist begrenzt. Es startet den Server aus Kapitel 5, loopback_demo.serve_clients, in einem Thread für einen Client auf 127.0.0.1 0. Dann verbindet es sich mit dem Client der Bibliothek, connect(...) aus websockets.sync.client, sendet eine Text- und eine Binärnachricht und liest jedes Echo, sendet einen und wartet höchstens 2 Sekunden auf den Pong und verlässt den with-Block, was die Verbindung schließt. In Lektion 3 schreibst du einen Client wie diesen. Führe es aus:

python interop.py

Ein Lauf dieser Dateien auf der Website hat Folgendes ausgegeben. PORT steht für die Portnummer, die das System gewählt hat; deine wird abweichen:

interop: the Chapter 5 server is listening on 127.0.0.1:PORT
library client: the handshake succeeded
library client: echo 'hello from the websockets library'
library client: echo b'\x00\x01\x02'
library client: ping answered: True
library client: closed the connection
Chapter 5 server: [{'messages': 2, 'code': 1000}]
interop: server thread still running: False

Lies es Zeile für Zeile. Der ist gelungen: Die Bibliothek hat eine Upgrade-Anfrage mit ihrem eigenen neuen Schlüssel gesendet, check_upgrade hat mit einer 101 geantwortet, die den von accept_value berechneten Accept- trug, und die Bibliothek hat diesen Wert so geprüft, wie es dein check_accept_response tut. Die beiden Echos werden mit repr ausgegeben, das einen Wert so schreibt, wie er im Python-Quelltext stünde: Anführungszeichen um einen str, ein b vor bytes. Die Bibliothek hat also einen Text-Frame und einen binären Frame maskiert, der Server aus Kapitel 5 hat sie demaskiert und dekodiert, und die Echos kamen als Text und als binär zurück. Der Ping wurde beantwortet: Die Bibliothek hat einen Ping mit b"interop" gesendet, server_reply hat mit einem Pong mit denselben Bytes geantwortet, und das Warten hat innerhalb seiner 2 Sekunden True zurückgegeben. Das Verlassen des Blocks hat Close 1000 gesendet, und der eigene Bericht des Servers zeigt, dass er diesen Close wiederholt hat: zwei Nachrichten, Code 1000. Zuletzt war der Server-Thread beendet.

Um deinen eigenen Code aus Kapitel 5 in diesem Lauf zu sehen, kopiere die Datei des Kurses mit cp loopback_demo.py course_loopback_demo.py beiseite, füge deine über loopback_demo.py ein und führe python interop.py erneut aus. Nichts prüft diesen Lauf; stelle danach mit cp course_loopback_demo.py loopback_demo.py die Version des Kurses wieder her, weil spätere Lektionen sie verwenden.

Was zeigt der Interop-Lauf?

Deine Arbeit prüfen

Klicke auf Check my work. Es liest requirements.txt und sonst nichts: genau eine websockets-Zeile, websockets==17.4, und die Zeile pytest==9.1.1 muss noch da sein; Kommentare und Leerzeilen sind in Ordnung. Es sieht sich weder .venv an, das nicht gespeichert wird, noch den Interop-Lauf.

Die Bibliothek hat mit deinem Server geredet und mit ihm übereingestimmt. In der nächsten Lektion kehren sich die Rollen um: Dein Server aus Kapitel 5 wird zu einem Server der Bibliothek, einem Handler von ein paar Zeilen.

Aufgabe

Lege die Bibliothek in requirements.txt fest: Füge die Zeile websockets==17.4 hinzu und behalte die Zeile pytest==9.1.1.

Dann im :

  1. python -c "import websockets; print(websockets.__version__)", um die eigene Version der Sandbox zu sehen;

  2. python -m venv .venv und .venv/bin/python -m pip install -r requirements.txt, um aus dem Paketspiegel des Kurses zu installieren;

  3. .venv/bin/python -m pip freeze, und such nach websockets==17.4;

  4. python interop.py, um zuzusehen, wie der Client der Bibliothek mit dem Server aus Kapitel 5 redet.

Klicke auf Check my work, wenn die Festlegung in der Datei steht. Die Prüfung liest nur requirements.txt: Sie erwartet genau eine Zeile, die nennt, geschrieben als websockets==17.4, ohne >= oder ~= und nicht nur in einem Kommentar, und sie erwartet, dass pytest==9.1.1 noch da ist. Kommentare, Leerzeilen und die Reihenfolge der beiden Zeilen sind dir überlassen. Die Prüfung sieht sich weder .venv an, das die Website nicht speichert, noch das, was interop.py ausgegeben hat.