Programmieren

mit Python

Python: Fehlerbehandlung

Ein mächtiges Feature das uns Python für die Entwicklung eigener Applikationen zur Verfügung stellt, ist ein ausgeklügeltes Fehlerbehandlungssystem. Fehler in einem Programm können immer auftreten, sei diese aufgrund falscher oder fehlerhafter Benutzereingaben, Systemfehlern, Laufzeitfehler etc. Umso bedenklicher ist es eigentlich dass Fehlerbehandlungssysteme nur in sehr wenigen Programmiersprachen direkt zur Verfügung gestellt werden: Java, C++, Python - also die objektorientierten Sprachen - besitzen ein solches, aber zum Beispiel Perl, C und auch die auf dem WWW meistgenutzte Sprache PHP besitzen (noch) keines -> PHP wird mit PHP5 ein solches aufweisen.

Im Computerchargon spricht man bei Fehlern von Bugs, wenn ein Fehler während der Auführung eines Programms auftritt, spricht man von einer Exception (Ausnahme).

Definition von Exceptions:

Eine wunderschöne Definition fand ich im englischen Buch The quick Python Book:

Generating an exception is called raising or throwing an exception.
Detecting a thrown exception, and calling code to act on it, is called catching an exception.
The called code (the code which actually handles the exception) is the exception-handling code or just exception handler.

In Python steht uns für die Ausnahmenbehandlung die try-except-Klausel zur Verfügung. Im try-Block listen wir die normalen Programmbefehle auf, im except-Block dann was gemacht werden muss wenn ein Fehler (eine Ausnahme) passiert.
D.h wir geben Python an, versuche (engl. try) zuerst den normalen Programmteil durchzuführen, und wenn ein Fehler auftritt führe den Ausnahmenbereich (engl. except) aus.

Programmabbruch verhindern:

Fangen wir zuerst einfach an. Im folgenden Beispiel wollen wir eine Fehlerbehandlungsroutine einbauen, die uns erlaubt bei fehlerhaften Benutzereingaben das Programm sanft und mit einem Hinweis zu beenden.
Erinnern wir uns, dass die input-Funktion nur Zahlen entgegennehmen kann, wenn also der Benutzer Zeichen eingibt, müssen wir dies abfangen und dem Benutzer mitteilen.

try:
  eingabe = input("Bitte eine Zahl eingeben: ")
  print "Du hast die Zahl", eingabe, "richtig eingegeben"
except:
  print "falsche Eingabe"

Zuerst wird versucht der normale Programmteil innerhalb des try-Blocks auszuführen. Ist dies erfolgreich so wird der except-Block übersprungen. Falls allerdings ein Fehler auftritt, so wird dieser mit der except-Anweisung abgefangen und alle Befehle die in diesem Block stehen ausgeführt. Anschliessend läuft das Programm ohne Abbruch zu Ende, da der Fehler zwar auftrat aber abgefangen wurde.
Beachte: nur die kritische Stelle wird in die Ausnahmebehandlung eingebettet. Man hat die Möglichkeit, unterschiedliche Fehlerarten in spezifischen except-Blöcken abzufangen. Dies hat den Vorteil, dass die Fehlermeldung präzisiert werden kann.

Fehler abfangen:

Das oben aufgeführte Beispiel ist zwar schon ein wichtiger Schritt zur erfolgreichen Fehlerbehandlung, aber aus Sicht des Benutzers sicher noch nicht optimal: Nach einer falschen Eingabe wird er zwar informiert, hat aber keine Möglichkeit seine Eingabe zu wiederholen. Wir wollen unser Beispiel also erweitern und den Fehler abfangen aber zugleich dem Benutzer die Möglichkeit zu einer erneuten Eingabe bieten.

fehler = 1
while fehler == 1:
  try:
    eingabe = input("Bitte eine Zahl eingeben: ")
    print "Du hast die Zahl", eingabe, "richtig eingegeben"
    fehler = 0
  except:
    print "falsche Eingabe"

Wir betten unser Programm in eine Schleife, die solange wiederholt wird, bis der Benutzer eine richtige Eingabe macht. Wir brauchen ein kleines Hilfsmittel in Form einer Schleifenvariable deren Wert wir ändern sobald die Eingabe richtig war, die Schleifenbedingung also nicht mehr zutrifft und wir aus dieser ausbrechen können.

Fehler erzeugen:

Wir haben nicht nur die Möglichkeit auf fest eingebaute Fehler zu reagieren, sondern können auch eigene Fehler erzeugen um in eine Ausnahmenbehandlung zu gelangen. Folgendes Beispiel erläutert dies, indem wir bei Eingabe einer zu grossen oder zu kleinen Zahl einen Fehler erzeugen und die Eingabe wiederholen lassen.

fehler = 1
while fehler == 1:
  try:
    eingabe = input("Bitte eine Zahl zwischen 0 und 1000 eingeben: ")
    # Eingabe zu gross oder zu klein
    if eingabe > 1000 or eingabe < 0:
      raise
    fehler = 0
  except:
    print "falsche Eingabe, bitte wiederholen"

print "Du hast die Zahl", eingabe, "richtig eingegeben"
print "Ende gut alles gut"

Unterscheidung von Ausnahmen:

Bisher wurde geschildert wie ein Programm durch das Abfangen von Fehlern gegen Abstürze gesichert werden kann. Die Fehler wurden dabei allgemein, d.h. ohne Angabe der Fehlerart abgefangen.

Im folgenden Programm sollen verschiedene Arten von Fehlern spezifisch abgefangen werden. Damit kann ein Benutzer wesentlich genauer über Fehlerursachen informiert werden. Wir wollen den Kehrwert einer Zahl ermitteln und auf mehrere mögliche Fehler reagieren:

fehler = 0
while not fehler:
  try:
    zahl = input("Bitte eine Zahl <> 0 eingeben: ")
    if zahl < 0:
      raise StandardError, "Zahl zu klein"
    kw = 1.0 / zahl
    fehler = 1
  except NameError:
    print "Fehler: Zeichen zu beginn eingegeben"
  except ZeroDivisionError:
    print "Fehler: Zahl 0 eingegeben"
  except StandardError, e:
    print "Fehler: ", e

print "Der Kehrwert von", zahl, "ist", kw