7.1 Erstellung benutzerdefinierter Exceptions
Manchmal reichen die Standard-Exceptions von Python nicht aus, um die Anforderungen deiner Anwendung vollständig zu erfüllen. In solchen Fällen kannst du deine eigenen Exceptions erstellen, indem du sie von der Basisklasse Exception oder einer anderen geeigneten Exception-Klasse ableitest.
Grundlagen der Erstellung benutzerdefinierter Exceptions
Die Erstellung einer benutzerdefinierten Exception umfasst die Definition einer neuen Klasse, die von der Basisklasse Exception abgeleitet wird. Du kannst eigene Methoden und Attribute in deine Exception-Klasse hinzufügen, um zusätzliche Informationen über den Fehler bereitzustellen.
Beispiel für die Erstellung einer einfachen benutzerdefinierten Exception
Schritt 1: Definition der benutzerdefinierten Exception
class MyCustomError(Exception):
"""Klasse für die benutzerdefinierte Exception."""
pass
Schritt 2: Verwendung der benutzerdefinierten Exception
def check_value(value):
if value < 0:
raise MyCustomError("Der Wert darf nicht kleiner als Null sein")
try:
check_value(-1)
except MyCustomError as e:
print(f"Eine benutzerdefinierte Exception ist aufgetreten: {e}")
Es ist ganz einfach. Wichtig ist, dass deine Exception von der Klasse Exception oder einem ihrer Nachkommen abgeleitet ist.
7.2 Erstellung einer Exception mit zusätzlichen Attributen
Du kannst deinem Exception-Klasse Attribute und Methoden hinzufügen, um zusätzliche Informationen über den aufgetretenen Fehler zu übermitteln.
Beispiel:
class NegativeValueError( Exception ):
"""Klasse für die benutzerdefinierte Exception bei negativem Wert."""
def __init__(self, value, message = "Der Wert darf nicht kleiner als Null sein"):
self.value = value
self.message = message
super().__init__(self.message)
def __str__(self):
return f'{self.message}: {self.value}'
Verwendung der Exception mit zusätzlichen Attributen
def check_value(value):
if value < 0:
raise NegativeValueError(value)
try:
check_value(-1)
except NegativeValueError as e:
print(f"Eine benutzerdefinierte Exception ist aufgetreten: {e}")
Unsere Exception ist eine Klasse, die von der Klasse Exception abgeleitet ist. Daher kannst du damit alles machen, was du auch mit jeder anderen Klasse tun kannst: Felder, Methoden, Konstruktorparameter hinzufügen usw.
Alles für deinen Komfort und den Komfort der Entwickler, die deine Exceptions abfangen werden.
7.3 Erstellung einer Hierarchie benutzerdefinierter Exceptions
Für komplexere Anwendungen ist es nützlich, Hierarchien benutzerdefinierter Exceptions zu erstellen. Dies ermöglicht die Gruppierung verwandter Exceptions und vereinfacht deren Behandlung.
Beispiel:
class ApplicationError(Exception):
"""Basisklasse für alle Anwendungs-Exceptions."""
pass
class NegativeValueError(ApplicationError):
"""Klasse für die benutzerdefinierte Exception bei negativem Wert."""
def __init__(self, value, message="Der Wert darf nicht kleiner als Null sein"):
self.value = value
self.message = message
super().__init__(self.message)
def __str__(self):
return f'{self.message}: {self.value}'
class ValueTooLargeError(ApplicationError):
"""Klasse für die benutzerdefinierte Exception bei zu großem Wert."""
def __init__(self, value, message="Der Wert ist zu groß"):
self.value = value
self.message = message
super().__init__(self.message)
def __str__(self):
return f'{self.message}: {self.value}'
Verwendung der Hierarchie benutzerdefinierter Exceptions
def check_value(value):
if value < 0:
raise NegativeValueError(value)
elif value > 100:
raise ValueTooLargeError(value)
try:
check_value(150)
except NegativeValueError as e:
print(f"Eine Exception ist aufgetreten: {e}")
except ValueTooLargeError as e:
print(f"Eine Exception ist aufgetreten: {e}")
except ApplicationError as e:
print(f"Allgemeine Anwendungs-Exception: {e}")
7.4 Reihenfolge des Exception-Abfangens
Beim Abfangen von Exceptions, insbesondere aus einer Hierarchie, ist es wichtig, ihre richtige Reihenfolge anzugeben. Und obwohl der Code innerhalb der except-Blöcke niemals gleichzeitig ausgeführt wird, liegt es daran, dass die Basisklasse der Exception in der Lage ist, Exceptions aller abgeleiteter Klassen abzufangen.
Zum Beispiel der Code:
def check_value(value):
if value < 0:
raise NegativeValueError(value)
elif value > 100:
raise ValueTooLargeError(value)
try:
check_value(150)
except ApplicationError as e: # fängt Exceptions des Typs ApplicationError und alle davon abgeleiteten Klassen ab
print(f"Allgemeine Anwendungs-Exception: {e}")
Im except-Block werden Exceptions vom Typ ApplicationError und aller seiner abgeleiteten Klassen abgefangen.
Und da alle Exceptions Nachkommen der Klasse Exception sind, würde so ein Code tatsächlich alle Exceptions abfangen:
def check_value(value):
if value < 0:
raise NegativeValueError(value)
elif value > 100:
raise ValueTooLargeError(value)
try:
check_value(150)
except Exception as e:
print(f"Alle Exceptions abfangen: {e}")
except ApplicationError as e: # Dieser Code wird nie ausgeführt
print(f"Allgemeine Anwendungs-Exception: {e}")
Das Abfangen von Exceptions im Block except ApplicationError wird nie stattfinden, da der Block except Exception tatsächlich alle Exceptions des Typs Exception und aller seiner abgeleiteten Klassen abfängt.
Lösung
Daher werden Exceptions in der umgekehrten Reihenfolge der Vererbung abgefangen: je näher die Klasse an der Klasse Exception ist, desto weiter unten steht sie.
Beispiel:
def check_value(value):
if value < 0:
raise NegativeValueError(value)
elif value > 100:
raise ValueTooLargeError(value)
try:
check_value(150)
except NegativeValueError as e:
print(f"Eine Exception ist aufgetreten: {e}")
except ApplicationError as e:
print(f"Allgemeine Anwendungs-Exception: {e}")
except Exception as e:
print(f"Alle Exceptions abfangen: {e}")
In diesem Beispiel sind die except-Blöcke in einer Reihenfolge angeordnet, die ihrer Vererbungshierarchie entspricht: Zuerst werden spezifischere Exceptions wie NegativeValueError abgefangen, dann allgemeinere wie ApplicationError. Dies ermöglicht eine korrekte Behandlung der Exceptions und verhindert Situationen, in denen ein allgemeinerer Handler die Ausnahme abfängt, bevor speziellere except-Blöcke dies könnten.
GO TO FULL VERSION