6. Ausnahmen
Wir werden uns nun mit Ausnahmen befassen.
![]() |
Das erste Skript veranschaulicht die Notwendigkeit, Ausnahmen zu behandeln.
Wir lösen absichtlich einen Fehler aus, um die vom Interpreter ausgegebenen Informationen zu sehen. Die Ausgabe lautet wie folgt:
Zeile 4 liefert uns:
- den Ausnahmetyp: ZeroDivisionError;
- die zugehörige Fehlermeldung: Ganzzahlige Division oder Modulo durch Null. Sie ist auf Englisch. Das möchten Sie vielleicht ändern.
Die grundlegende Regel beim Programmieren lautet, dass wir alles tun müssen, um „unkontrollierte“ Abstürze wie den oben genannten zu vermeiden. Selbst im Falle eines Fehlers muss das Programm ordnungsgemäß beendet werden und Informationen über den aufgetretenen Fehler bereitstellen.
Die Syntax für die Ausnahmebehandlung lautet wie folgt:
try:
actions susceptibles de lancer une exception
except [classe d'exception, ...]:
actions de gestion de l'exception
finally:
actions toujours exécutées qu'il y ait exception ou non
Im try-Block wird die Ausführung der Aktionen beendet, sobald eine Ausnahme auftritt. In diesem Fall wird die Ausführung mit den Aktionen in der except-Klausel fortgesetzt.
Die
except [MyException, ...]:
fängt Ausnahmen vom Typ MyException oder davon abgeleiteten Typen ab. Wenn in einem try-Block eine Ausnahme auftritt, prüft der Interpreter die mit dem try-Block verbundenen except-Klauseln in der Reihenfolge, in der sie geschrieben wurden. Er hält bei der ersten except-Klausel an, die die aufgetretene Ausnahme behandeln kann. Findet er keine, wird die Ausnahme an die aufrufende Methode zurückgegeben. Verfügt diese Methode über einen try/except-Block, wird die Ausnahme erneut behandelt; andernfalls wird sie weiter in der Kette der aufgerufenen Methoden nach oben weitergeleitet. Schließlich erreicht sie den Python-Interpreter. Der Interpreter beendet dann das laufende Programm und zeigt eine Fehlermeldung des im vorherigen Beispiel gezeigten Typs an. Die Regel lautet daher, dass das Hauptprogramm alle Ausnahmen abfangen muss, die von aufgerufenen Methoden weitergeleitet werden können.
Eine Ausnahme enthält Informationen über den aufgetretenen Fehler. Diese Informationen können mit der folgenden Syntax abgerufen werden:
except MyException as informations:
information ist ein Tupel, das die Informationen zur Ausnahme enthält.
Die Syntax
except MyException, erreur:
weist der Variablen error die mit der Ausnahme verbundene Fehlermeldung zu.
Um eine Ausnahme auszulösen, verwenden Sie die Syntax
raise MyException(param1, param2, ...)
wobei MyException meist eine von der Klasse Exception abgeleitete Klasse ist. Die an den Klassenkonstruktor übergebenen Parameter stehen der except-Klausel von Strukturen zur Ausnahmebehandlung zur Verfügung.
Diese Konzepte werden durch das folgende Skript veranschaulicht.
Das folgende Skript behandelt Fehler explizit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
Anmerkungen:
- Zeilen 6–9: Behandlung einer Division durch Null;
- Zeile 8: Wir fangen genau die aufgetretene Ausnahme ab;
- Zeile 11: Aufgrund der aufgetretenen Ausnahme hat x keinen Wert erhalten und sich daher nicht verändert;
- Zeilen 15–19: Wir machen dasselbe, fangen aber eine übergeordnete Ausnahme vom Typ Exception ab. Da die Ausnahme ZeroDivisionError von der Klasse Exception abgeleitet ist, wird sie von der except-Klausel abgefangen;
- Zeilen 23–33: Wir fügen mehrere except-Klauseln ein, um mehrere Ausnahmetypen zu behandeln. Es wird nur eine except-Klausel ausgeführt oder gar keine, wenn die Ausnahme keiner except-Klausel entspricht;
- Zeilen 51–55: Die except-Klausel darf keine Argumente haben. In diesem Fall fängt sie alle Ausnahmen ab;
- Zeilen 59–62: Einführung der ValueError-Ausnahme;
- Zeilen 66–69: Abrufen der von der Ausnahme enthaltenen Informationen;
- Zeilen 73–76: Erläuterung, wie eine Ausnahme ausgelöst wird;
- Zeilen 79–84: Veranschaulichung der Verwendung einer benutzerdefinierten Ausnahmeklasse, MyError;
- Zeilen 79–80: Die Klasse „MyError“ erbt einfach von der Basisklasse „Exception“. Sie fügt ihrer Basisklasse nichts hinzu. Nun kann sie jedoch in „except“-Klauseln explizit genannt werden;
- Zeilen 97–107: zeigen, dass man in Python tatsächlich jede Art von Objekt auslösen kann, nicht nur Objekte, die von der Klasse
*Exceptionabgeleitet sind;* - Zeilen 109–127: veranschaulichen die Verwendung der finally-Klausel.
Die Bildschirmausgabe lautet wie folgt:
0 : integer division or modulo by zero
x=2
1 : integer division or modulo by zero
2 : (Exception) integer division or modulo by zero
3 : (ZeroDivisionError) integer division or modulo by zero
4 : il y a eu un probleme
5 : invalid literal for int() with base 10: 'x'
6 : invalid literal for int() with base 10: 'x'
7 : ('param1', 'param2', 'param3')
8 : ('info1', 'info2', 'info3')
9 : mon msg d'erreur
10 : pb...
11 : finally x=1
12 : exception
12 : finally x=None
Dieses neue Skript veranschaulicht, wie Ausnahmen entlang der Kette der aufrufenden Methoden weitergeleitet werden:
Anmerkungen:
- Zeilen 27–30: Beim Aufruf main --> f1 --> f2 --> f3 (Zeile 28) wird die von f3 ausgelöste MyError-Ausnahme bis zu main weitergeleitet. Sie wird dann durch die except-Klausel in Zeile 29 abgefangen;
- Zeilen 55–58: Im Aufruf main → f4 → f5 → f6 (Zeile 56) wird die von f6 ausgelöste MyError-Ausnahme bis nach main weitergeleitet. Sie wird dann von der except-Klausel in Zeile 29 abgefangen. Während sie diesmal die Kette der aufrufenden Methoden hinaufwandert, wird die MyError-Ausnahme um Informationen angereichert, die von jeder Methode auf dem Weg hinzugefügt werden.
Die Bildschirmausgabe lautet wie folgt:
