27. Exceptions

Was ist, wenn die Datei nicht existiert?

>>> f = open("junk")
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
IOError: [Errno 2] No such file or directory:
'junk'

Sowas heißt Exception und ist ein allgemeiner Mechanismus zur Fehlerbehandlung. Es gibt verschiedene Sorten von Exceptions:

  • SyntaxError – es ist ein syntaktischer Fehler im Quelltext
  • IOError – eine Datei existiert nicht, man darf nicht schreiben, die Platte ist voll
  • IndexError – in einer Sequenz gibt es das angeforderte Element nicht
  • KeyError – ein Mapping hat den angeforderten Schlüssel nicht
  • ValueError – eine Operation kann mit diesem Wert nicht durchgeführt werden (Wurzel aus negativen Zahlen, int für einen String wie "bla")

(und viele mehr).

Exceptions kann man behandeln:

>>> import sys
>>> try:
...     f = open("junk")
... except IOError:
...     sys.stderr.write("Hilfe...\n")
...
Hilfe...

Anmerkungen:

  • Die Syntax von try...except folgt der normalen Syntax von Python: nach try: und except: wird eingerückt, was hinter try kommt, wird ausgeführt, bis ein Fehler auftritt, was hinter except kommt, wird nur ausgeführt, wenn im try-statement eine Exception der angegebenen Art aufgetreten ist.
  • Hinter except können ein oder mehrere Exception-Typen stehen (wenn es mehrere sind, in Klammern durch Kommata getrennt schreiben). Wenn keine Typen angegeben ist, reagiert das except auf alle Exceptions (was man allenfalls dann tun sollte, wenn eine Exception dann immer noch eine sichtbare Fehlermeldung erzeugt – ein except:, bei dem anschließend die Exception ignoriert wird, ist die sicherste Art, die Fehlersuche fast unmöglich zu machen).
  • sys ist ein Modul, in dem allerlei Sachen stehen, die etwas mit dem “System” zu tun haben, etwa die Standardein- und -ausgabe, Funktionen zum Abbrechen des Programms oder zum Verarbeiten von tracebacks, der Pfad, auf dem Python nach Modulen sucht und vieles mehr.
  • sys.stderr ist eine in sys vordefinierte Datei, der Standardfehlerkanal. Fehlermeldungen sollten immer dorthin ausgegeben werden. Vorteil: Sie werden immer noch gesehen, auch wenn die Standardausgabe (dorthin gibt print aus) umgeleitet ist. In sys gibt es noch zwei weitere Dateien: sys.stdin, die Standardeingabe (von dort liest raw_input) und sys.stdout (die erwähnte Standardausgabe). Es ist eine von fast allen anderen Systemen übernommene Unix-Tradition, möglichst alles im Rechner als Datei darzustellen, insbesondere also auch “Tastatur” und “Monitor” (das sollte man jetzt allerdings nicht so wörtlich nehmen).

Hinter einem try: können mehrere except-statements für verschiedene Typen von Exceptions kommen, und schließlich noch ein else-statement, der ausgeführt wird, wenn keine Exception ausgelöst wurde.

Exceptions kann man auch selbst auslösen:

>>> raise IOError("Brainless User")
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
IOError: Brainless User

Hinter raise steht also ein (normalerweise) mit einem String instanziertes Exception-Objekt.

Eine gewisse Sonderrolle hat die Exception KeyboardInterrupt. Sie wird ausgelöst, wenn die Benutzerin Control-C drückt (allgemeiner die Interrupt-Taste, noch allgemeiner, wenn das Programm das INT-Signal (vgl. man signal) geschickt bekommt). Auch diese Exception kann man fangen.

Schließlich gibt es noch das nicht wirklich mit Exceptions zusammenhängende try...finally-Konstrukt, bei dem, ganz egal, was im try:-statement passiert, der Code hinter finally: auf jeden Fall ausgeführt wird. So etwas ist praktisch, um in kritischen Codepassagen am Ende wieder einen definierten Zustand herzustellen. Wir werden später Beispiele dafür sehen.

Übungen zu diesem Abschnitt

Ihr solltet euch wenigstens an den rötlich unterlegten Aufgaben versuchen

(1)

Probiert, Exeptions der erwähnten Arten auszulösen und zu fangen.

(2)

Wie kann man ein Programm schreiben, dass noch schnell “Röchel” sagt, wenn es durch ein Control-C abgebrochen wird? Kann man auf diese Weise Control-Cs ganz ignorieren?

(3)

Um zu verstehen, was das mit stderr und stdout soll, schreibt euch ein Programm, das nach einer Weile eine Fehlermeldung ausgibt, einmal auf stderr, einmal auf stdout, also etwa so:

import time, sys

time.sleep(3)
sys.stderr.write("Fehler!!!\n")

Ruft dieses Programm von der Kommandozeile aus auf und leitet die Ausgabe in eine Datei um (das geht auch unter DOS/Windows):

examples> python prog.py > junk

Was beobachtet ihr?


Markus Demleitner

Copyright Notice