Mit Exceptions lassen sich Fehlerzustände aus einer Methode nach außen übermitteln.
Rückgabewerte
Wie kann eine Methode machWas
() in der Klasse Service
im Modul Worker
der aufrufenden Umgebung mitteilen, dass sie aufgrund eines Fehlers nicht korrekt arbeiten kann.
Die früher übliche Methode, mit einem zurückgebenen Statuscode zu arbeiten, hat einen Haken.
if Service.machWas() == 0:
print('Erfolg')
else:
print('Fehlschlag')
Zum einen muss genau festgelegt werden, für welchen Fehler, welcher Statuscode zurückgeliefert wird, um dann darauf zu reagieren. Zum anderen macht das spätestens dann Probleme, wenn die Methode ei bestimmtes Ergebnis zurückliefern soll. Gut, letzteres ließe sich über ein Tupel lösen, ist aber bei externen Modulen schwierig.
Exceptions
Exceptions sind in der OOP eine elegantere Möglichkeit, aus einer Methode eine Statusmeldung zurückzugeben. Ich hatte das im letzten Kapitel schonmal kurz benutzt.
def func(wert):
if not isinstance(wert,int):
raise TypeError('wert muss ein int sein.')
if wert > 0:
print('Wert ist in Ordnung')
else:
raise ValueError('wert muss größer 0 sein')
func(7)
func(-1)
Die Methode func
() benötigt einen Integer Parameter, der größer als 0
sein muss.
Dazu prüft sie mit isinstance
(), ob wert ein int
ist und wirft im negativen Fall mittels raise
einen TypeError
.
Ist wert
kleiner als 0
wird ein ValueError
zurückgeworfen.
Exceptions werden in Python mit dem Schlüsselwort raise
geworfen. Danach folgt eine Instanz einer Klasse, die von Exception ableitet (was alle internen Error-Klassen machen). Dem Konstruktor jeder Exception kannst du einen erläuterten Text mitgeben.
Exception fangen
Wenn du eine Exception mit raise
wirfst, kannst du sie auch fangen. Dazu dient das try-except
Konstrukt
def func(wert):
if not isinstance(wert,int):
raise TypeError('weertr muss ein int sein.')
if wert >0:
print('Wert ist in Ordnung')
else:
raise ValueError('wert muss größer 0 sein')
func(7)
try:
func(-1)
except ValueError:
print('Da haben wir doch einen falschen Wert übergeben.')
Im except
Block kannst du mögliche „Rettungsversuche“ des Methodenaufrufs auslösen oder aber den Anwender benachrichtigen, ein Problem, dass den Programmablauf stört zu beseitigen ( bspw. Drucker einschalten, Datenträger mounten u.ä.)
finally
Es gibt immer wieder mal die Situation, dass ein Codeblock ausgeführt werden muss, egal, ob eine Exception geflogen ist oder nicht. Dazu leistet dir finally
gute Dienste, das einfach an einen try/except
Block angeschlossen wird.
# encode utf-8
def func(wert):
if not isinstance(wert,int):
raise TypeError('weertr muss ein int sein.')
if wert >0:
print('Wert ist in Ordnung')
else:
raise ValueError('wert muss größer 0 sein')
func(7)
try:
func(-1)
except ValueError:
print('Da haben wir doch einen falschen Wert übergeben.')
finally:
# Dieser Block wird immer ausgeführt, egal ob mit oder ohne Exception
# Hier kannst z.B. Datenbankverbindungen schliessen, Speicher freigeben oder temporäre Dateien löschen
pass
Eigene Exceptions
Wenn dir die Python internen Exceptions nicht ausreichen oder nicht sprechend genug sind, kannst du sehr einfach eine eigene Exception definieren. Sie ist einfach nur eine Klasse, die von Exception
ableitet, in der Datei meineexception.py
definieren wir unsere MeineException
class MeineException(Exception):
pass
Mit zwei Zeilen Code ist es schon getan.
Im Programm myexception.py benutzen wir die eigene Exception nun:
from meineexception import MeineException
def func():
raise MeineException('meine eigene Exception')
func()
Gerade in eigenen Packages und Modulen sind Exceptions sehr nützlich, um dem aufrufenden Programmcode Fehlerzustände anzuzeigen. Im Gegensatz zu dem alten Verfahren, dies mit Rückgabewerten zu tun sind Exceptions meist selbsterklärend und besser lesbar.
Im nächsten Teil zeig ich dir, wie du verschiedene Datentypen konvertieren kannst.