Geschichte der Frage:
Das Ausnahmesystem (exceptions) wurde ursprünglich in Python eingeführt und basiert auf Klassen. Die gesamte Hierarchie von Ausnahmen wird von der Basisklasse BaseException abgeleitet. In der Praxis werden eigene Ausnahmen von Exception abgeleitet. Die Entwicklung von benutzerdefinierten Ausnahmen ist wichtig für große Projekte — sie ermöglicht eine genauere Verarbeitung und Signalgebung spezifischer Anwendungsfehler.
Problem:
Nicht alle Entwickler verstehen die Unterschiede zwischen BaseException und Exception, sie scheuen sich, eigene Klassen zu erstellen, verwenden allgemeine Catch-Blöcke, was zur Verdrängung unerwünschter Ausnahmen (z. B. SystemExit, KeyboardInterrupt) und schwer zugänglichen Bugs führt. Häufig werden Ausnahme-Klassen inkorrekt implementiert — sie geben keinen sinnvollen Namen an und erben nicht von der richtigen Klasse.
Lösung:
Eigene Ausnahmen als Nachkommen von Exception schreiben. Sinnvolle Namen verwenden, um nicht alle grundlegenden Fehler zu erfassen. Nicht von BaseException erben, sondern nur von Exception oder deren Abkömmlingen und nicht alles mit except: ohne Angabe einer spezifischen Klasse abfangen.
Beispielcode:
class MyAppError(Exception): """Basis-Klasse für Anwendungs-Ausnahmen""" pass class ConfigFileNotFound(MyAppError): pass try: raise ConfigFileNotFound('Konfigurationsdatei nicht gefunden!') except ConfigFileNotFound as e: print(f'Fehler: {e}')
Wichtige Merkmale:
Warum ist es gefährlich, alle Ausnahmen mit "except:" ohne Angabe eines Typs abzufangen?
Ein solcher Block fängt sogar Systemausnahmen — KeyboardInterrupt, SystemExit, was eine reguläre Beendigung des Programms bei Ctrl+C unmöglich macht und zu "Hängern" in kritischen Situationen führt. Man sollte "except Exception:" schreiben, um grundlegende Systemereignisse zu überspringen.
Kann man seine eigene Ausnahme von BaseException ableiten?
Technisch ist das möglich, aber dringend davon abzuraten — solche Ausnahmen sind schwer zu erkennen, sie umgehen die Standardbehandler von Exception, was oft zu nicht fassbaren Fehlern in der Anwendung führt.
Ist es richtig, ValueError oder TypeError anstelle von benutzerdefinierten Ausnahmen zu verwenden?
In kleinen Skripten ist das akzeptabel, aber in großen Projekten ist es besser, eigene semantisch sinnvolle Ausnahmen zu erstellen. Dies beschleunigt die Diagnose und Verarbeitung von Fehlern auf höheren Ebenen der Anwendung.
# Falsch: raise ValueError('Etwas spezifisches für die Anwendung') # Gut: class MyAppValueError(MyAppError): pass raise MyAppValueError('Fehlerbeschreibung im Kontext der Anwendung')
In einem großen Projekt gab es einen globalen try/except: Block, der auch Systemausnahmen abfing. Eine Reihe von Fehlern (z. B. SystemExit) wurden nicht im Log ausgegeben, die Anwendung geriet in unerwartete Zustände und Administratoren suchten lange nach den Symptomen.
Vorteile:
Nachteile:
Es wurden eigene Fehlerklassen definiert, es wurde überall nur "except Exception: ..." verwendet und separate Behandler für benutzerdefinierte Ausnahmen.
Vorteile:
Nachteile: