Exceptions¶
In diesem Abschnitt geht es um Ausnahmen, d.h. um Sprachfunktionen, die speziell ungewöhnliche Umstände während der Ausführung eines Programms behandeln. Die häufigste Ausnahme ist die Behandlung von Fehlern, aber sie können auch für viele andere Zwecke effektiv eingesetzt werden. Python bietet einen umfassenden Satz von Ausnahmen, und ihr könnt neue Ausnahmen für eure eigenen Zwecke definieren.
Der gesamte Exception-Mechanismus in Python ist objektorientiert: Eine Exception ist ein Objekt, das automatisch von
Python-Funktionen mit einer raise-Anweisung erzeugt wird. Diese
raise-Anweisung veranlasst die Ausführung des Python-Programms auf eine
andere Art und Weise, als üblicherweise vorgesehen: Die aktuelle Aufrufkette
wird nach einem Handler durchsucht, der die erzeugte Ausnahme behandeln kann.
Wenn ein solcher Handler gefunden wird, wird er aufgerufen und kann auf das
Ausnahmeobjekt zugreifen, um weitere Informationen zu erhalten. Wird kein
geeigneter Exception-Handler gefunden, bricht das Programm mit einer
Fehlermeldung ab.
Bemerkung
Die Art und Weise, wie Python Fehlersituationen im Allgemeinen behandelt, unterscheidet sich von manch anderen Sprachen, z.B. Java. Diese Sprachen prüfen mögliche Fehler so weit wie möglich, bevor sie auftreten, da die Behandlung von Exceptions nach ihrem Auftreten kostspielig ist. Dies wird manchmal als LBYL-Ansatz bezeichnet.
Bei Python hingegen verlässt man sich eher auf Exceptions, um Fehler zu behandeln, nachdem sie aufgetreten sind. Obwohl dieses Vertrauen riskant erscheinen mag, ist der Code weniger schwerfällig und leichter zu lesen, wenn Exceptions richtig eingesetzt werden, und Fehler werden nur dann behandelt, wenn sie auftreten. Diese pythonische Herangehensweise zur Behandlung von Fehlern wird oft als EAFP beschrieben.
Es ist möglich, verschiedene Arten von Ausnahmen zu erzeugen, um die
tatsächliche Ursache des gemeldeten Fehlers oder außergewöhnlichen Umstandes zu
reflektieren. Eine Übersicht über die Klassenhierarchie eingebauter Exceptions
erhaltet ihr unter Exception hierarchy in der
Python-Dokumentation. Jeder Ausnahmetyp ist eine Python-Klasse, die von ihrem
übergeordneten Exception-Typ erbt. So ist z.B. ein
ZeroDivisionError durch Vererbung auch ein ArithmeticError, eine
Exception und auch eine BaseException. Diese Hierarchie ist gewollt: Die
meisten Ausnahmen erben von Exception, und es wird dringend empfohlen, dass
alle benutzerdefinierten Ausnahmen auch die Unterklasse von Exception und
nicht von BaseException bilden:
1class EmptyFileError(Exception):
2 pass
Dies definiert ihr euren eigenen Ausnahmetyp, der vom Basistyp Exception
erbt.
5filenames = ["myFile1.py", "nonExistent.py", "emptyFile.py", "myFile2.py"]
Eine Liste unterschiedlicher Datei-Arten wird definiert.
Schließlich werden Ausnahmen oder Fehler mit Hilfe der zusammengesetzten
Anweisung try-except-else-finally abgefangen und behandelt.
Jede Ausnahme, die nicht abgefangen wird, führt zur Beendigung des Programms.
7for file in filenames:
8 try:
9 f = open(file, "r")
10 line = f.readline()
11 if line == "":
12 raise EmptyFileError(f"{file} is empty")
13 except OSError as error:
14 print(f"Cannot open file {file}: {error.strerror}")
15 except EmptyFileError as error:
16 print(error)
17 else:
18 print(f"{file}: {f.readline()}")
19 finally:
20 print("File", file, "processed")
21 f.close()
- Zeile 7
Wenn während der Ausführung der Anweisungen im
try-Block einOSErroroderEmptyFileErrorauftritt, wird der zugehörigeexcept-Block ausgeführt.- Zeile 9
Hier könnte ein
OSErrorausgelöst werden.- Zeile 12
Hier löst ihr den
EmptyFileErroraus.- Zeile 17
Die
else-Klausel ist optional; sie wird ausgeführt, wenn imtry-Block keine Ausnahme auftritt.Bemerkung
In diesem Beispiel hätte stattdessen auch
continue-Anweisungen in denexcept-Blöcken verwendet werden können.- Zeile 19
Die
finally-Klausel ist optional; sie wird am Ende des Blocks ausgeführt, unabhängig davon, ob eine Ausnahme ausgelöst wurde oder nicht.
Checks¶
Schreibt Code, der zwei Zahlen erhält und die erste Zahl durch die zweite dividiert. Prüft, ob der
ZeroDivisionErrorauftritt, wenn die zweite Zahl0ist, und fangt diese ab.Wenn
MyErrorvonExceptionerbt, was ist dann der Unterschied zwischenexcept Exception as eundexcept MyError as e?Schreibt ein einfaches Programm, das eine Zahl erhält und dann die Anweisung
assert()verwendet, um eineExceptionauszulösen, wenn die Zahl0ist.Schreibt eine benutzerdefinierte Ausnahme
Outliers, die eineExceptionauslöst, wenn die Variablexgrößer oder kleiner als3ist?Handelt es sich bei der Überprüfung, ob ein Objekt eine Liste ist (Check: list) um eine Programmierung im Stil von LBYL oder EAFP?