2.25. Fehler behandeln¶
Die meisten Laufzeitprobleme in Python treten als Ausnahmen zutage – eine benannte, strukturierte Möglichkeit, zu melden, dass etwas schiefgelaufen ist. ValueError, TypeError, KeyError, OSError, MemoryError sind allesamt Beispiele; jede ist eine Klasse, und das Auslösen (Raising) einer Ausnahme stoppt den aktuellen Aufruf und sucht im umgebenden Code nach einem Handler.
2.25.1. try / except¶
Umschließen Sie einen Codeblock mit try, um jede von ihm ausgelöste Ausnahme abzufangen:
try:
n = int(input_text)
except ValueError:
n = 0
Wenn die Umwandlung int(...) fehlschlägt, springt die Steuerung zum except-Block, anstatt den Fehler weiter zu propagieren. Wenn input_text ein gültiger Ganzzahl-String war, wird der except-Block übersprungen.
Ein einzelnes try kann mehrere except-Blöcke haben, von denen jeder eine andere Art von Fehler abfängt:
try:
value = data[key]
except KeyError:
value = None
except TypeError:
value = -1
Python gleicht der Reihe nach ab; der erste, dessen Ausnahmeklasse passt, behandelt das Problem. Das Abfangen von Exception (der Basisklasse für fast alles) behandelt jeden Fehler; reservieren Sie das für die äußerste Schicht eines Programms, wo die Alternative ein Absturz wäre.
Warnung
Ein bloßes except: (keine Klasse nach dem Schlüsselwort) fängt auch KeyboardInterrupt ab – die Ausnahme, die die IDE sendet, wenn Sie ihren Stop-Knopf drücken, um ein laufendes Skript zu unterbrechen. Eine Schleife, die in ein bloßes except: pass gehüllt ist, verschluckt die Unterbrechung und läuft weiter, sodass es keine Möglichkeit mehr gibt, das Skript zu stoppen, außer durch Aus- und Einschalten.
Bevorzugen Sie except Exception: gegenüber dem bloßen except:, wenn Sie wirklich breit abfangen müssen. KeyboardInterrupt erbt von BaseException, nicht von Exception, sodass except Exception: den Stop-Knopf funktionsfähig lässt.
2.25.1.1. Die Ausnahme untersuchen¶
Um die an eine Ausnahme angehängte Nachricht zu lesen, benennen Sie sie mit as:
try:
f = open("data.txt")
except OSError as e:
print("could not open file:", e)
Die mit as gebundene Variable ist nur innerhalb des except-Blocks gültig.
2.25.2. else und finally¶
Ein try-Block hat zwei optionale Ergänzungen.
else wird nur ausgeführt, wenn der try-Block beendet wurde, ohne eine Ausnahme auszulösen:
try:
value = compute()
except ValueError:
print("bad input")
else:
print("got", value)
„Was zu tun ist, wenn es funktioniert hat“ in else zu legen, hält den try-Block schmal – nur die Zeile, die fehlschlagen könnte, gehört in try.
finally wird am Ende ausgeführt, egal was passiert – ob der try-Block erfolgreich war, eine Ausnahme auslöste und sie behandelt wurde oder eine Ausnahme auslöste und sie gleich propagiert wird:
try:
do_work()
finally:
cleanup()
finally wird immer ausgeführt. else wird nur auf dem Pfad ohne Ausnahme ausgeführt.¶
Für die meisten Belegen/Freigeben-Muster ist ein Kontextmanager einem try / finally-Paar vorzuziehen – die Ressource verwaltet ihre eigene Aufräumarbeit selbst.
2.25.3. Häufige eingebaute Ausnahmen¶
Eine kurze Liste der Ausnahmen, denen Sie häufig begegnen werden:
ValueError– richtiger Typ, falscher Wert (bytes([300])– 300 ist der richtige Typ, liegt aber außerhalb des gültigen Byte-Bereichs von 0..255).TypeError– ganz falscher Typ (len(42)).IndexError– Index über das Ende einer Sequenz hinaus.AttributeError– Zugriff auf ein Attribut, das nicht existiert ("abc".foo).OSError– ein Dateisystem- oder E/A-Fehler.MemoryError– der Heap ist erschöpft. Auf einer speicherbeschränkten Laufzeitumgebung kann dies während des normalen Betriebs auftreten – nicht nur in pathologischen Fällen.