Kapitel 9
Wenn die Außenwelt Probleme macht
Erst reproduzieren, dann korrigieren
Bevor du anfängst, noch eine Sache: Die Kopie des Katalogprojekts in diesem Kapitel enthält einen Fehler, den wir absichtlich eingebaut haben. Du hast in Kapitel 8 nichts falsch gemacht, und die bereitgestellten Dateien sind nicht versehentlich fehlerhaft. Fehlersuche ist eine Fähigkeit, für die man etwas Defektes zum Üben braucht. Hier ist es.
Deine Aufgabe ist, den Fehler so zu finden, wie du einen echten finden würdest. Das bedeutet, dem Drang zu widerstehen, sofort mit dem Bearbeiten anzufangen.
Der Katalogbefehl meldet fehlerhafte Eingaben bereits ohne Traceback. Das ist nützlich, aber nicht jeder Fehler sollte gleich aussehen. Halte vor jeder Codeänderung vier Tatsachen fest: das Arbeitsverzeichnis, die genaue Argumentliste, die Eingabebytes und das beobachtete Symptom.
Beginne im Bash-Bereich im Projektstamm und führe den Befehl aus:
pwd
python catalog.py catalog.csv selected.json --minimum-quantity 4
cat selected.json
Der Befehl schreibt einen Artikel. Der Vertrag aus Kapitel 8 besagt, dass die Option Artikel behält, deren Menge mindestens dem Schwellenwert entspricht. Ein Artikel mit Menge 4 sollte bei einem Schwellenwert von 4 also erhalten bleiben. Erwartet wurden zwei Artikel.
Korrigiere es noch nicht. Was du jetzt hast, ist wertvoller als eine Korrektur: ein reproduzierbarer Fall für die Fehlersuche. Du kennst das Verzeichnis (/workspace), den genauen Befehl, die genaue Eingabedatei und das genaue falsche Ergebnis. Sobald sich eines davon ändert, ist es ein anderer Fall.
Gerade diesen letzten Punkt überspringen viele. Einen Befehl erneut auszuführen zählt nur dann als Beleg, wenn alles darum herum gleich geblieben ist. Ein anderes Verzeichnis, ein anderer Schwellenwert, eine bearbeitete CSV-Datei: Schon betrachtest du ein neues Problem und glaubst, es sei noch das alte.
Drei Zuständigkeiten für Fehler
Führe einen Befehl aus, bei dem ein Pfad fehlt:
python catalog.py catalog.csv
Argparse gibt einen Aufrufhinweis und einen Fehler auf stderr aus und endet dann mit Status 2. Die Konvertierung startet nie. Das ist ein Schnittstellenfehler: Der Befehl entsprach nicht seiner öffentlichen Grammatik.
Gib jetzt eine Eingabedatei an, die nicht existiert:
python catalog.py missing.csv selected.json
Der Befehl entspricht der Grammatik, aber die Außenwelt kann die angeforderte Datei nicht liefern. Das ist ein erwarteter externer Fehler. Das Programm versteht die fehlgeschlagene Operation gut genug, um eine kurze Diagnose und Status 1 zu liefern.
Ein Programmierfehler ist etwas anderes. Starte Pythons interaktive Eingabeaufforderung:
python
Lass dann die Auswahlfunktion einen Artikel verarbeiten, der eine interne Kataloginvariante verletzt:
>>> import catalog
>>> catalog.select_items([{}], 4)
Das erzeugt einen Traceback, der mit KeyError: 'quantity' endet. Die Dateischnittstelle ist nicht fehlgeschlagen. Projektcode hat eine Struktur erhalten, die nach der Validierung angeblich nicht vorkommen kann. Daraus „could not read the catalog“ zu machen würde die Hinweise verbergen, die du zur Korrektur des Programms brauchst.
Verlasse die interaktive Eingabeaufforderung, bevor du zu Bash zurückkehrst:
>>> exit()
Den Traceback vom Ergebnis zur Ursache lesen
Beginne bei der letzten Zeile. Sie nennt Ausnahmetyp und Meldung: KeyError: 'quantity'. Gehe dann nach oben zum innersten Aufrufrahmen im Projektcode. Dieser Rahmen nennt catalog.py, die Zeile in select_items und den Ausdruck, der den fehlenden Schlüssel lesen wollte.
Frühere Aufrufrahmen erklären, wie die Ausführung dorthin gelangt ist. Sie liefern Kontext und sind nicht automatisch die Stelle, die du bearbeiten solltest. Die erste nützliche Frage lautet: Welche innerste Projektoperation hat eine Annahme verletzt?
python catalog.py source.csv zeigt den Aufrufhinweis von argparse an und endet mit Status 2. Welche Zuständigkeit solltest du zuerst untersuchen?
Ein Traceback endet mit KeyError: 'quantity', und der innerste Projektaufrufrahmen zeigt in select_items. Was solltest du zuerst untersuchen?
Als Nächstes hältst du den formal erfolgreichen, aber falschen Lauf vor seinem Vergleich an und untersuchst die Werte, die entscheiden, ob der Artikel am Grenzwert erhalten bleibt.