Abschnitt 9 · Lektion 5
Debuggen
Das Programm gibt Im Schnitt: 2.12 Euro aus, läuft ohne Meldung durch, und die Zahl ist falsch.
Die meisten Fehler bisher waren rot, mit Traceback und Zeilennummer. Am Anfang fühlt sich das nicht
so an, aber das ist die angenehme Sorte.
Die unangenehme gab es in diesem Abschnitt auch schon ein paar Mal. Den Dienstag mit 0.0 Grad, die
0.00 Euro hinter dem except ohne Fehlerart, den Rabatt von 150 Prozent. Ein Traceback hilft da
nicht, denn für Python ist alles in Ordnung. Es hat getan, was dasteht. Nur steht nicht da, was
gemeint war.
Ein Fehler im Programm heißt auf Englisch bug, also Käfer, und ihn zu suchen heißt debuggen (debugging). Es gibt eine hübsche Geschichte dazu, nach der in einem Rechner von 1947 eine echte Motte steckte. Nur war das Wort damals schon älter.
Ein Programm, das lügt
preise = [3.20, 0, 2.90, 3.20, 4.50]
summe = 0
for i in range(1, len(preise)):
summe = summe + preise[i]
print(f"Im Schnitt: {summe / len(preise):.2f} Euro") Das ist die Kaffeewoche aus Abschnitt 4 und 5 mit fünf Tagen, und 2.12 Euro klingen erst mal nach Kaffee. Keine Meldung, alles grün. In Lektion 5.4 kamen für dieselbe Woche aber 2.76 Euro heraus. Eins von beiden stimmt nicht.
Hier steckt der erste Schritt jeder Fehlersuche, und mit Werkzeugen hat er nichts zu tun. Du musst wissen, was ungefähr herauskommen soll. 3.20, 0, 2.90, 3.20 und 4.50 sind zusammen 13.80, und durch fünf sind das 2.76. Erst wenn du diese Zahl im Kopf hast, ist die 2.12 überhaupt ein Fehler.
Für den ersten Lauf eines neuen Programms lohnen sich deshalb Daten, die man im Kopf nachrechnen kann. Wenige Werte, runde Zahlen und, wenn es geht, ein Fall mit offensichtlicher Antwort.
Zwischenstände mit print
preise = [3.20, 0, 2.90, 3.20, 4.50]
summe = 0
for i in range(1, len(preise)):
summe = summe + preise[i]
print(f"{i=} {summe=}")
print(f"Im Schnitt: {summe / len(preise):.2f} Euro") Am schnellsten geht es mit einem zusätzlichen print an der Stelle, an der du nicht mehr sicher
bist, was passiert. Neu ist nur das Gleichheitszeichen im f-String. Mit f"{summe=}" steht nicht
nur der Wert da, sondern auch der Name davor, also summe=0. Wenn mehrere Werte in einer Zeile
stehen, weißt du so sofort, welcher welcher ist.
Und schon die erste Zeile verrät alles. Sie lautet i=1 summe=0. In der ersten Runde ist i schon
1, und dazugekommen ist der Preis vom Dienstag, der 0 war. Die 3.20 vom Montag stehen an Position 0,
und die kommt in keiner Runde dran. range(1, len(preise)) fängt eben bei 1 an.
Solche Zeilen sind zum Suchen da, nicht zum Bleiben. Sobald der Fehler gefunden ist, kommen sie wieder raus. Viele Aufgaben in diesem Kurs prüfen die ganze Ausgabe, und dann wird die Prüfung durch jede zusätzliche Zeile rot. In einem echten Programm stünden sie sonst irgendwann in einem Bericht, den jemand anderes liest.
Jeder Schritt im Reiter Debug
Das zweite Werkzeug kennst du seit Lektion 1.5. Beim ersten Beispiel, dem ohne print, wird mit
Aufzeichnen im Reiter Debug der Lauf aufgezeichnet. In der Liste steht jede Zeile, die
gelaufen ist, und zwar in der Reihenfolge, in der sie lief. Am Rand steht der Wert, der sich seit
dem Schritt davor geändert hat. Wenn du einen Schritt wählst, siehst du darunter die Werte, wie sie
vor dieser Zeile waren, draußen die des Programms und in einer Funktion die der Funktion.
Die Zeile mit der Summe kommt viermal vor, nicht fünfmal. Beim ersten Mal steht i schon auf 1. Auf
0 steht i in der ganzen Aufzeichnung nie.
Am Code musst du dafür nichts ändern und hinterher nichts aufräumen. Außerdem siehst du alle Werte
dieser Stelle auf einmal und nicht nur die, an die du beim Schreiben der print-Zeile gedacht hast.
Bei einer langen Schleife wird die Liste dafür lang. Dann hilft es, erst mit print die Runde zu
finden, in der es schiefgeht, und nur diese im Reiter anzusehen. Eine Aufzeichnung zählt übrigens
wie jeder andere Lauf auf dein Kontingent.
Laut erklären
Das dritte Werkzeug braucht keinen Rechner. Man erklärt den Code Zeile für Zeile, laut, jemandem, der nichts davon versteht. Unter Programmierern hat das einen albernen Namen, Gummienten-Debugging, weil manche dafür tatsächlich eine Gummiente auf dem Schreibtisch stehen haben.
Beim Beispiel oben klingt das so. „Die Summe fängt bei null an. Dann kommen alle Preise dran, von Position 1 bis zum Ende …“ Spätestens hier stockt man, denn der erste Preis hat die Position 0. Beim Lesen überspringt das Auge so etwas. Beim Sprechen nicht, weil man jedes Wort einzeln sagen muss. Meistens fällt der Fehler auf, bevor die Ente irgendetwas sagen muss.
preise = [3.20, 0, 2.90, 3.20, 4.50]
summe = 0
for preis in preise:
summe = summe + preis
print(f"Im Schnitt: {summe / len(preise):.2f} Euro") Behoben ist es mit einer Schleife, die gar keine Positionen braucht. Dann stehen da 2.76 Euro.
Oft steckt in einem Programm mehr als ein Fehler. Wenn einer behoben ist, rechnet man noch einmal nach. Kommt dann eine neue falsche Zahl heraus, ist es nicht schlimmer geworden. Es ist einfach der nächste Fehler, der jetzt sichtbar wird.
Was die Aufgabe will
Ein Sparplan-Rechner zeigt, wie viel Geld nach ein paar Jahren mit Zinsen da ist, und läuft ohne jede Meldung durch. Seine Zahlen sind trotzdem falsch, und zwar alle. Mit den drei Werkzeugen von oben lassen sich die Fehler finden und beheben.
Zum Mitnehmen
Am schwersten zu finden ist der Fehler ohne Meldung, bei dem das Programm durchläuft und eine falsche Zahl ausgibt. Zuerst braucht es ein Ergebnis, das man selbst nachrechnen kann. Danach kommen drei Werkzeuge in Frage, print mit f"{wert=}", der Reiter Debug und das laute Erklären, Zeile für Zeile.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 3 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.