Home | Lehre | Videos | Texte | Vorträge | Software | Person | Impressum, Datenschutzerklärung | Blog RSS

Stand: 2025-04-02
weitgehend formuliert von ChatGPT 4o, verbessert von Claude 3.7 Sonnet, redigiert/korrigiert von Jörn Loviscach

Exceptions

Was sind Exceptions?

Exceptions sind Fehler, die während der Laufzeit eines Programms auftreten können. Diese Fehler unterbrechen den normalen Programmablauf und können, wenn sie nicht behandelt werden, zum Absturz des Programms führen. Beispiele für solche Fehler sind:

Exceptions erlauben einen übersichtlicheren Programmcode: Man schreibt den Programmcode für den Normalfall komplett in ein try und dahinter getrennt davon die Fehlerbehandlung in ein oder mehrere except. Ohne Exceptions müsste der Programmcode dagegen bei allen Schritten, die fehlschlagen können, ein if mit einer Verzweigung zur Fehlerbehandlung enthalten, so dass der Normalfall und die Fehlerbehandlung auf schwer zu lesende Art vermischt wären. Außerdem erübrigen Exceptions die in C üblichen Fehlercode-Rückgabewerte von Funktionen, was ebenfalls zur Übersichtlichkeit beiträgt.

Die Blöcke try und except

Mit dem try und except kann man Fehler (Exceptions) abfangen und behandeln, anstatt dass das Programm abstürzt. Hier ist ein einfaches Beispiel:

try:
    zahl = int(input("Gib eine Zahl ein: "))
    ergebnis = 10 / zahl
    print(f"Das Ergebnis ist {ergebnis}")
except ZeroDivisionError:
    print("Fehler: Division durch Null ist nicht erlaubt!")
except ValueError:
    print("Fehler: Bitte eine gültige Zahl eingeben!")

Erklärung:

  1. try-Block: Hier kommt der Code, der möglicherweise einen Fehler erzeugen könnte. Sobald ein Fehler auftritt, wird dieser Block sofort mittendrin abgebrochen. Wenn zum Beispiel in der Zeile ergebnis = 10 / zahl durch Null geteilt werden soll, kommt das Programm gar nicht mehr dazu, die Variable ergebnis anzulegen oder zu ändern.
  2. except-Block: Hier kommt der Code, der ausgeführt wird, wenn ein bestimmter Fehler auftritt. In diesem Fall behandeln wir zwei spezifische Klassen von Fehlern, die in Python vordefiniert sind:

Will man möglichst viele Arten von Fehlern fangen (vielleicht, nachdem die spezielleren Fehler schon wie oben gefangen sind), man dahinter ein except: ohne Angabe eines konkreten Fehlertyps setzen:

except:
    print("Fehler")

Es gibt allerdings Fehler, die sich nicht so fangen lassen, zum Beispiel, dass im Programm ein Syntaxfehler ist.

Der finally-Block

Dem try und einem oder mehreren except kann wahlweise ein finally-Block folgen. Er wird immer ausgeführt, unabhängig davon, ob ein Fehler aufgetreten ist und ob er behandelt worden ist. Dies ist nützlich, um Aufräumarbeiten durchzuführen, zum Beispiel das Schließen von Dateien oder das Freigeben von Datenbanken.

try:
    datei = open("beispiel.txt", "r")
    inhalt = datei.read()
    print(inhalt)
except FileNotFoundError:
    print("Fehler: Datei nicht gefunden!")
finally:
    if 'datei' in locals():  # Wurde die Variable datei angelegt?
        datei.close()
        print("Datei wurde geschlossen.")

Erklärung:

  1. try-Block: Versucht, die Datei zu öffnen und ihren Inhalt zu lesen.
  2. except-Block: Behandelt den Fehler, wenn die Datei nicht gefunden wird.
  3. finally-Block: Stellt sicher, dass die Datei geschlossen wird, unabhängig davon, ob ein Fehler aufgetreten ist und ob er behandelt worden ist.

Verwendet man with zur Arbeit mit Dateien (siehe das Thema Dateien im entsprechenden früheren Skript), dann ist das passende finally schon eingebaut.

Selbstdefinierte Exceptions

Manchmal möchte man eigene Arten von Fehlern definieren und behandeln. Dazu dienen selbstdefinierte Exceptions. Sie erben von der Klasse Exception oder einer deren Unterklassen wie ValueError:

class UngültigeEingabeError(Exception):
    pass  # Man könnte hier auch Methoden und Attribute haben.

def benutzer_eingabe():
    eingabe = input('Gib "ja" oder "nein" ein: ').lower()
    if eingabe not in ['ja', 'nein']:
        raise UngültigeEingabeError('Ungültige Eingabe! Bitte nur "ja" oder "nein" eingeben.')
    return eingabe

try:
    antwort = benutzer_eingabe()
    print(f'Du hast "{antwort}" eingegeben.')
except UngültigeEingabeError as e:  # Die Exception in die Variable e holen
    print(e)
finally:
    print('Programm beendet.')

Erklärung:

  1. Selbstdefinierte Exception: Die Klasse UngültigeEingabeError wird definiert. Sie erbt von der in Python vordefinierten Klasse der allgemeinen Exception.
  2. Fehler auslösen: In der Funktion benutzer_eingabe wird mittels raise die benutzerdefinierte Exception ausgelöst, wenn die Eingabe nicht ja oder nein ist.
  3. try-except-finally: Der Fehler wird abgefangen und eine entsprechende Nachricht ausgegeben. Der finally-Block wird immer ausgeführt.

Man beachte, dass das raise typischerweise an einer ganz anderen Stelle steht als das try ... except. Sobald ein Fehler auftritt, also das Programm auf das raise stößt, werden der Code in der Funktion benutzer_eingabe und der Code im try unmittelbar abgebrochen. Das Programm springt dann zum passenden except. Gibt es kein passendes except oder ist man sogar in keinem try, wird das Programm abrupt beendet (Absturz).

Zusammenfassung