mitmario.dev

try und except

Python Sandbox 3 Min Lesezeit 4 BeispieleLektion 2 von 6

In einer Liste mit Preisen steht ein einziger als Wort da, zwei Euro statt 2.00, und das ganze Programm ist vorbei. Solange der Fehler im Code steckt, ist das richtig. Dann soll er laut sein.

Anders ist es bei Fehlern, die von draußen kommen. Eine Datei, die jemand von Hand gefüllt hat, oder eine Antwort, die jemand eingetippt hat, enthält irgendwann ein Wort statt einer Zahl. Das passiert nicht aus Versehen. Es ist der Normalfall, und man muss damit rechnen.

Ein Fehler beendet alles
preise = ["2.49", "1.19", "zwei Euro", "3.29"]
summe = 0
for preis in preise:
    summe = summe + float(preis)
print(f"Zusammen: {summe:.2f} Euro")

Vom ganzen Programm bleibt nur ValueError: could not convert string to float: 'zwei Euro'. Die zwei Preise davor waren schon zusammengezählt, der danach wäre es auch gewesen. Ausgegeben wird nichts davon. Ein einziger Eintrag, und die ganze Rechnung ist weg.

try und except

Abfangen und weitermachen
preise = ["2.49", "1.19", "zwei Euro", "3.29"]
summe = 0
for preis in preise:
    try:
        summe = summe + float(preis)
    except ValueError:
        print("Übersprungen:", preis)
print(f"Zusammen: {summe:.2f} Euro")

Unter try (versuchen) steht ein Block, von dem du weißt, dass er schiefgehen kann. Darunter folgt except mit der Fehlerart, die du erwartest, hier ValueError. Wenn dieser Fehler im try-Block auftritt, bricht Python nicht ab, sondern springt in den except-Block, führt ihn aus und macht danach hinter dem Ganzen weiter. Geht alles gut, wird der except-Block übersprungen. Eingerückt sind beide Blöcke wie bei if und else.

Bei zwei Euro steht im Beispiel deshalb die Zeile Übersprungen: zwei Euro. Die Schleife läuft weiter, und am Ende kommt Zusammen: 6.97 Euro heraus, die Summe der drei Preise, die sich lesen ließen.

Ein Fehler, der erst beim Laufen entsteht, heißt bei Python übrigens Ausnahme (exception). Daher hat except seinen Namen.

Wichtig ist, wo das try steht. Davon hängt ab, was nach dem Fehler noch passiert. Hier steht es in der Schleife, nur um die eine Zeile, die scheitern kann, und deshalb geht es mit dem nächsten Preis weiter. Stünde es um die ganze Schleife, wäre nach dem ersten Fehler auch die Schleife vorbei. Nur eben ohne Traceback. Je kleiner der try-Block, desto genauer ist klar, womit man gerechnet hat.

Was genau schiefging

Was genau schiefging
preise = ["2.49", "1,19", "", "3.29"]
summe = 0
for preis in preise:
    try:
        summe = summe + float(preis)
    except ValueError as fehler:
        print("Übersprungen:", fehler)
print(f"Zusammen: {summe:.2f} Euro")

Hinter except ValueError kann as mit einem Namen stehen, hier fehler. Unter diesem Namen hast du im except-Block den Fehler selbst. print gibt seine Meldung aus, also den Text, der sonst hinter ValueError: in der letzten Zeile des Tracebacks stünde.

Im Beispiel sind es zwei Meldungen, einmal mit '1,19' und einmal mit ''. Die Anführungszeichen helfen dabei sehr. Ohne sie stünde beim leeren Text hinter dem Doppelpunkt einfach nichts, und du wüsstest nicht, ob dort ein Leerzeichen war oder gar nichts.

Zwei Wörter gibt es noch, die man seltener braucht. Ein else: nach dem except läuft nur, wenn im try kein Fehler auftrat. Ein finally: läuft immer, mit Fehler und ohne. Das ist für Aufräumarbeiten gedacht, die auf keinen Fall ausfallen dürfen.

Nie einfach alles abfangen

Ein except für alles
preise = ["2.49", "1.19", "zwei Euro", "3.29"]
summe = 0
for preis in preise:
    try:
        summe = summe + flaot(preis)
    except:
        print("Übersprungen:", preis)
print(f"Zusammen: {summe:.2f} Euro")

Python erlaubt auch ein except: ganz ohne Fehlerart. Dann wird jeder Fehler abgefangen. Das sieht praktisch aus und ist der Fehler dieser Lektion.

Im Beispiel steht flaot statt float, ein Tippfehler. Gemeldet wird er nicht. Auch ein NameError ist ein Fehler, und das except: fängt ihn genauso ab wie die echten Fehler in den Daten. Jeder Preis wird übersprungen, am Ende stehen 0.00 Euro da, und nirgends steht, warum.

Mit ValueError hinter dem except meldet sich der Tippfehler sofort, als NameError: name 'flaot' is not defined. Did you mean: 'float'?. Die Fehlerart hinter except ist das, womit du rechnest. Alles andere ist ein Fehler im Programm und soll laut bleiben. Welche Fehlerart du brauchst, steht in der letzten Zeile des Tracebacks, den du ohne try bekommen hast.

Im Netz findet man oft except Exception:. Das sieht genauer aus, ist es aber nicht. Exception ist der Oberbegriff für fast alle Fehlerarten, auch für NameError, und der Tippfehler verschwindet damit genauso.

Was die Aufgabe will

Für das Sommerfest des Vereins hat jedes Mitglied in eine gemeinsame Liste eingetragen, wie viele Würstchen es essen will. Nicht alle haben eine Zahl geschrieben. Das Programm, das die Liste zusammenzählt, bricht beim ersten Wort ab. Am Ende soll es alle lesbaren Mengen zählen und jede andere melden.

Zum Mitnehmen

Unter try steht, was schiefgehen kann, und unter except, was dann passieren soll. Abgefangen wird immer nur eine bestimmte Fehlerart. Ohne sie verschwinden auch die Fehler, die man unbedingt sehen müsste, zum Beispiel ein Tippfehler im eigenen Code.

Jetzt du

Basis Konto, kostenlos

Zu 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 4 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe, dein Code läuft auf einem Server

    Öffnet sich mit dem Basis Konto.