Course
Ausnahme- und Fehlerbehandlung in Python
Fehler und Ausnahmen können zu unerwartetem Verhalten führen oder sogar die Ausführung eines Programms verhindern. Python bietet verschiedene Funktionen und Mechanismen, um diese Probleme zu lösen und die Robustheit des Codes zu verbessern. In diesem Tutorium lernen wir verschiedene Fehlertypen kennen und lernen die eingebauten Funktionen anhand von Beispielen kennen.
Ein Fehler ist ein Problem in einem Programm, das das Programm daran hindert, seine Aufgabe zu erfüllen. Im Vergleich dazu ist eine Ausnahme eine Bedingung, die den normalen Programmablauf unterbricht. Sowohl Fehler als auch Ausnahmen sind eine Art Laufzeitfehler, das heißt, sie treten während der Ausführung eines Programms auf.
Mit einfachen Worten: Ein Fehler ist ein kritisches Problem, das eine normale Anwendung nicht abfangen sollte, während eine Ausnahme ein Zustand ist, den ein Programm abfangen sollte.
Wir wollen mehr über Fehler und Ausnahmen lernen, indem wir uns verschiedene Beispiele ansehen. Um diese einfach auszuführen, kannst du eine kostenlose DataLab-Arbeitsmappe erstellen, auf der Python vorinstalliert ist und die alle Codebeispiele enthält.
Fehler in Python
Hier ist ein Beispiel für einen Syntaxfehler, bei dem ein Return außerhalb der Funktion nichts bedeutet. Wir sollten keine Fehler in einem Programm behandeln. Stattdessen müssen wir eine Funktion erstellen, die den String zurückgibt.
return "DataCamp"
Input In [1]
return "DataCamp"
^
SyntaxError: 'return' outside function
Wir haben die Funktion erstellt, aber mit der falschen Einrückung. Wir sollten keine Einrückungsfehler zur Laufzeit behandeln. Entweder wir machen es manuell oder verwenden Code-Formatierungstools.
def fun():
return "DataCamp"
Input In [2]
return "DataCamp"
^
IndentationError: expected an indented block
Ausnahmen in Python
Es ist ein ZeroDivisionError (Exception) aufgetreten. Wir können es zur Laufzeit mit `try` und `except` Blöcken behandeln.
test = 1/0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Input In [4], in <cell line: 1>()
----> 1 test = 1/0
ZeroDivisionError: division by zero
NameError-Ausnahmen sind recht häufig, wenn eine Variable nicht gefunden wird. Wir können die Ausnahme auch behandeln, indem wir entweder die Variable ersetzen oder die Warnung ausgeben.
y = test
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [5], in <cell line: 1>()
----> 1 y = test
NameError
Eingebaute Python-Ausnahmen
Hier ist die Liste der Standardausnahmen in Python mit Beschreibungen:
- AssertionError: wird ausgelöst, wenn die Assert-Anweisung fehlschlägt.
- EOFError: wird ausgelöst, wenn die input()-Funktion die End-of-File-Bedingung erfüllt.
- AttributeError: wird ausgelöst, wenn die Attributzuweisung oder -referenz fehlschlägt.
- TabError: wird ausgelöst, wenn die Einrückungen aus inkonsistenten Tabulatoren oder Leerzeichen bestehen.
- ImportError: wird ausgelöst, wenn der Import des Moduls fehlschlägt.
- IndexError: tritt auf, wenn der Index einer Sequenz außerhalb des Bereichs liegt
- KeyboardInterrupt: wird ausgelöst, wenn der Benutzer Unterbrechungstasten eingibt (Strg + C oder Löschen).
- RuntimeError: tritt auf, wenn ein Fehler in keine Kategorie fällt.
- NameError: wird ausgelöst, wenn eine Variable im lokalen oder globalen Bereich nicht gefunden wird.
- MemoryError: wird ausgelöst, wenn Programmen der Speicher ausgeht.
- ValueError: tritt auf, wenn die Operation oder Funktion ein Argument mit dem richtigen Typ, aber dem falschen Wert erhält.
- ZeroDivisionError: wird ausgelöst, wenn du einen Wert oder eine Variable durch Null teilst.
- SyntaxError: wird vom Parser ausgelöst, wenn die Python-Syntax falsch ist.
- IndentationError: tritt auf, wenn eine falsche Einrückung vorliegt.
- SystemError: wird ausgelöst, wenn der Interpreter einen internen Fehler feststellt.
Eine vollständige Liste der Fehler und Ausnahmen in Python findest du in der Dokumentation.
Lerne mehr über Python-Ausnahmen in unserem Kurs Objektorientierte Programmierung in Python. Du lernst, wie du Klassen erstellst und Vererbung und Polymorphie nutzt, um Code wiederzuverwenden und zu optimieren.
Behandlung von Ausnahmen mit try, except, else und finally
Nachdem wir etwas über Fehler und Ausnahmen gelernt haben, werden wir lernen, wie wir sie mit try-, except-, else- und finally-Blöcken behandeln.
Was verstehen wir also unter Umgang mit ihnen? Unter normalen Umständen halten diese Fehler die Codeausführung an und zeigen die Fehlermeldung an. Um stabile Systeme zu schaffen, müssen wir diese Fehler vorhersehen und alternative Lösungen oder Warnmeldungen entwickeln.
In diesem Abschnitt erfahren wir, was die einzelnen Blöcke tun und wie wir sie nutzen können, um robusten Code zu schreiben.
try und except Anweisung
Die einfachste Art, Ausnahmen in Python zu behandeln, ist die Verwendung des `try`- und `except`-Blocks.
- Führe den Code unter der Anweisung `try` aus.
- Wenn eine Ausnahme ausgelöst wird, führe den Code unter der Anweisung `except` aus.
Anstatt bei einem Fehler oder einer Ausnahme stehen zu bleiben, wird unser Code nach alternativen Lösungen suchen.
Einfaches Beispiel
Im ersten Beispiel werden wir versuchen, die undefinierte Variable "x" zu drucken. Unter normalen Umständen sollte er einen Fehler auslösen und die Ausführung stoppen, aber mit dem `try`- und dem `except`-Block können wir das Verhalten des Ablaufs ändern.
- Das Programm führt den Code unter der Anweisung `try` aus.
- Da wir wissen, dass `x` nicht definiert ist, wird die except-Anweisung ausgeführt und eine Warnung ausgegeben.
try:
print(x)
except:
print("An exception has occurred!")
An exception has occurred!
Beispiel für mehrere Except-Anweisungen
Im zweiten Beispiel werden wir mehrere "Except"-Anweisungen verwenden, um mehrere Arten von Ausnahmen zu behandeln.
- Wenn eine ZeroDivisionError-Ausnahme ausgelöst wird, gibt das Programm aus: "Du kannst einen Wert nicht durch Null dividieren."
- Bei den restlichen Ausnahmen wird "Etwas anderes ist schief gelaufen" gedruckt.
Sie ermöglicht es uns, flexiblen Code zu schreiben, der mehrere Ausnahmen gleichzeitig behandeln kann, ohne abzubrechen.
try:
print(1/0)
except ZeroDivisionError:
print("You cannot divide a value with zero")
except:
print("Something else went wrong")
You cannot divide a value with zero
Laden der Datei Beispiel
Schauen wir uns nun ein praktischeres Beispiel an.
Im folgenden Code lesen wir die CSV-Datei. Wenn die Ausnahme "FileNotFoundError" ausgelöst wird, gibt der Code den Fehler und eine zusätzliche Meldung über die Datei "data.csv" aus.
Ja, wir können Standard-Fehlermeldungen ausgeben, ohne die Ausführung zu unterbrechen.
try:
with open('data.csv') as file:
read_data = file.read()
except FileNotFoundError as fnf_error:
print(fnf_error)
print("Explanation: We cannot load the 'data.csv' file")
[Errno 2] No such file or directory: 'data.csv'
Explanation: We cannot load the 'data.csv' file
mit else-Klausel versuchen
Wir haben `try` und `except` kennengelernt und jetzt werden wir die `else`-Anweisung kennenlernen.
Wenn die "try"-Anweisung keine Ausnahme auslöst, tritt der Code in den "else"-Block ein. Sie ist die Abhilfe oder eine Rückfalloption, wenn du erwartest, dass ein Teil deines Skripts eine Ausnahme erzeugt. Sie wird in der Regel in einem kurzen Einrichtungs- oder Überprüfungsabschnitt verwendet, in dem du nicht willst, dass sich bestimmte Fehler verstecken.
Hinweis: Im try-except-Block kannst du das `else` nach allen `except`-Anweisungen verwenden.
Einfaches Beispiel
Wir fügen die `else`-Anweisung zum ZeroDivisionError-Beispiel hinzu. Wie wir sehen können, wird die Druckfunktion unter der Anweisung `else` ausgeführt, wenn es keine Ausnahmen gibt, und zeigt das Ergebnis an.
try:
result = 1/3
except ZeroDivisionError as err:
print(err)
else:
print(f"Your answer is {result}")
Your answer is 0.3333333333333333
IndexError mit else Beispiel
Wir wollen mehr darüber erfahren, indem wir eine einfache Funktion erstellen und sie für verschiedene Szenarien testen.
Die Funktion `find_nth_value` hat `x` (Liste) und `n` (Indexnummer) als Argumente. Wir haben einen try-, except- und else-Block erstellt, um die IndexError-Ausnahme zu behandeln.
x = [5,8,9,13]
def find_nth_value(x,n):
try:
result = x[n]
except IndexError as err:
print(err)
else:
print("Your answer is ", result)
Die Liste "x" hat vier Werte und wir werden sie auf den 6. und 2.
# Testing
find_nth_value(x,6)
find_nth_value(x,2)
- Bei n=6 wurde die IndexError-Ausnahme ausgelöst, und wir bekamen die Fehlermeldung "list index out of range" zu sehen.
- Bei n=2 wurde keine Ausnahme ausgelöst und die Funktion gab das Ergebnis aus, das unter der `else`-Anweisung steht.
list index out of range
Your answer is 9
finally Schlüsselwort in Python
Das Schlüsselwort `finally` im try-except-Block wird immer ausgeführt, unabhängig davon, ob es eine Ausnahme gibt oder nicht. In einfachen Worten: Der "final"-Block wird nach dem "try"-Block ausgeführt, nur der "else"-Block ist endgültig. Es ist sehr nützlich, um Ressourcen aufzuräumen und das Objekt zu schließen, insbesondere die Dateien zu schließen.
Die Funktion `divide` wird erstellt, um ZeroDivisionError-Ausnahmen zu behandeln und das Ergebnis anzuzeigen, wenn es keine Ausnahmen gibt. Egal, wie das Ergebnis aussieht, es wird immer `finally` ausgeführt, um "Code by DataCamp" in grüner Farbe zu drucken.
def divide(x,y):
try:
result = x/y
except ZeroDivisionError:
print("Please change 'y' argument to non-zero value")
except:
print("Something went wrong")
else:
print(f"Your answer is {result}")
finally:
print("\033[92m Code by DataCamp\033[00m")
Im ersten Test dividieren wir 1 durch 0, was die Ausnahme ZeroDivisionError auslösen und die Meldung ausgeben sollte. Wie wir sehen können, haben wir eine zusätzliche Zeile nach der Fehlermeldung.
divide(1,0)
Please change 'y' argument to non-zero value
Code by DataCamp
Wenn wir eine gültige Eingabe machen, zeigt sie das Ergebnis an, indem sie `else` und `finally` blockiert.
divide(3,4)
Your answer is 0.75
Code by DataCamp
Anstelle einer ganzen Zahl haben wir eine Zeichenkette als zweites Argument hinzugefügt, die eine Ausnahme ausgelöst hat, die sich von ZeroDivisionError unterscheidet und eine andere Meldung enthält.
divide(1,'g')
Something went wrong
Code by DataCamp
In allen drei Szenarien gibt es eine Gemeinsamkeit. Der Code führt immer die Druckfunktion unter der `finally`-Anweisung aus.
Wenn du neu in Python bist und wie ein echter Programmierer programmieren möchtest, dann probiere unseren Python-Programmierkurs aus. Du lernst, effizienten Code zu schreiben, Python-Funktionen, Softwaretechnik, Unit-Tests und objektorientierte Programmierung.
Verschachtelte Ausnahmebehandlung in Python
Wir brauchen eine verschachtelte Ausnahmebehandlung, wenn wir das Programm darauf vorbereiten, mehrere Ausnahmen in einer Folge zu behandeln. Wir können zum Beispiel einen weiteren try-except-Block unter der `else`-Anweisung hinzufügen. Also, wenn die erste Anweisung keine Ausnahme auslöst und die zweite Anweisung mit der anderen Hälfte des Codes überprüft.
Ändern der Divide-Funktion
Wir haben die Funktion `divide` aus dem vorherigen Beispiel geändert und einen verschachtelten try-except-Block unter der `else`-Anweisung hinzugefügt. Wenn es also keinen AttributeError gibt, wird die `else` ausgeführt und der neue Code auf die ZeroDivisionError-Ausnahme geprüft.
def divide(x,y):
try:
value = 50
x.append(value)
except AttributeError as atr_err:
print(atr_err)
else:
try:
result = [i / y for i in x]
print( result )
except ZeroDivisionError:
print("Please change 'y' argument to non-zero value")
finally:
print("\033[92m Code by DataCamp\033[00m")
Im ersten Szenario geben wir die Liste mit 3 Werten "x" und den Nenner 3 an. Das Skript fügt der Liste 50 hinzu und teilt den einzelnen Wert in der Liste durch 3 und zeigt das Ergebnis an.
x = [40,65,70,87]
divide(x,3)
Die Funktion wurde erfolgreich ausgeführt, ohne Ausnahmen auszulösen.
[13.333333333333334, 21.666666666666668, 23.333333333333332, 29.0, 16.666666666666668]
Code by DataCamp
Statt einer Liste haben wir eine ganze Zahl als erstes Argument angegeben, was zu einem AttributeError geführt hat.
divide(4,3)
'int' object has no attribute 'append'
Code by DataCamp
Im letzten Szenario haben wir die Liste mit 0 als zweites Argument angegeben, was die ZeroDivisionError-Ausnahme unter der `else`-Anweisung ausgelöst hat.
divide(x,0)
Please change 'y' argument to non-zero value
Code by DataCamp
Beispiel für Dateibearbeitung
Schauen wir uns weitere praktische Beispiele für das Laden der Datei, das Schreiben eines Textes und das Schließen der Datei an.
file_editor Funktion wird:
- Überprüfe die FileNotFoundError-Ausnahme für die Funktion `open()`.
- Wenn die äußere Ausnahme nicht ausgelöst wird, wird nach der Ausnahme der Funktion `write()` gesucht.
- Egal, was passiert, nachdem die Datei geöffnet wurde, wird sie mit der Anweisung `finally` geschlossen.
- Wenn die äußere try-Anweisung die Ausnahme auslöst, gibt sie die Fehlermeldung mit einem ungültigen Dateipfad zurück.
def file_editor(path,text):
try:
data = open(path)
try:
data.write(text)
except:
print("Unable to write the data. Please add an append: 'a' or write: 'w' parameter to the open() function.")
finally:
data.close()
except:
print(f"{path} file is not found!!")
Im ersten Szenario geben wir den Dateipfad und den Text an.
path = "data.txt"
text = "DataLab: Share your data analysis in a cloud-based environment--no installation required."
file_editor(path,text)
Die äußere Ausnahme wird ausgelöst.
data.txt file is not found!!
Um die Ausnahme "Datei nicht gefunden" zu lösen, müssen wir eine Datei "data.txt" mit dem Linux-Befehl "echo" erstellen.
!echo "File by DataCamp" > "data.txt"
Danach führst du die Funktion `file_editor()` erneut aus.
file_editor(path,text)
Die innere Exception wird ausgelöst, da die Funktion `write` den Text nicht hinzufügen kann.
Unable to write the data. Please add an append: 'a' or write: 'w' parameter to the open() function.
Um dieses Problem zu lösen, müssen wir die dritte Zeile von `data = open(path)` in `data = open(path, 'a')` ändern. Damit können wir den neuen Text an die Datei anhängen.
Nachdem wir die Funktion erneut ausgeführt haben, haben wir den Text erfolgreich zur Datei hinzugefügt.
file_editor(path,text)
Eine verschachtelte Ausnahmebehandlung wird nicht empfohlen, da sie die Ausnahmebehandlung komplexer macht. Stattdessen verwenden Entwickler mehrere try-except-Blöcke, um eine einfache sequenzielle Ausnahmebehandlung zu erstellen.
Hinweis: Du kannst auch einen verschachtelten try-except-Block unter die `try`- oder `except`-Anweisung setzen. Das hängt ganz von deinen Anforderungen ab.
Auslösen von Ausnahmen in Python
Als Python-Entwickler hast du die Möglichkeit, eine Ausnahme auszulösen, wenn bestimmte Bedingungen erfüllt sind. Es ermöglicht dir, das Programm nach deinen Bedürfnissen zu unterbrechen.
Um eine Ausnahme auszulösen, müssen wir das Schlüsselwort `raise` gefolgt von einem Ausnahmenamen verwenden.
Beispiel für das Auslösen eines Wertfehlers
Wir können Ausnahmen einfach auslösen, indem wir das Schlüsselwort raise in die if/else-Anweisung einfügen.
Im Beispiel lösen wir den Fehler ValueError aus, wenn der Wert größer als 1.000 ist. Wir haben den Wert auf 2.000 geändert, wodurch die "if"-Anweisung WAHR wurde und ValueError mit der benutzerdefinierten Meldung ausgelöst wurde. Die benutzerdefinierte Fehlermeldung hilft dir, das Problem schnell herauszufinden.
value = 2_000
if value > 1_000:
# raise the ValueError
raise ValueError("Please add a value lower than 1,000")
else:
print("Congratulations! You are the winner!!")
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
----> 4 raise ValueError("Please add a value lower than 1,000")
5 else:
6 print("Congratulations! You are the winner!!")
ValueError: Please add a value lower than 1,000
Beispiel für das Auslösen einer Ausnahme
Wir können auch eine beliebige integrierte Python-Ausnahme auslösen, wenn die Bedingung erfüllt ist. In unserem Fall haben wir eine generische "Exception" mit der Fehlermeldung ausgelöst.
if value > 1_000:
# raise the Exception
raise Exception("Please add a value lower than 1,000")
else:
print("Congratulations! You are the winner!!")
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
----> 3 raise Exception("Please add a value lower than 1,000")
4 else:
5 print("Congratulations! You are the winner!!")
Exception: Please add a value lower than 1,000
Beispiel für die Behandlung einer ausgelösten Ausnahme
Wir können auch unsere eigene Ausnahme erstellen und die Ausnahme mit dem try-except-Block behandeln.
Im Beispiel haben wir ein Beispiel für einen Wertfehler unter der Anweisung `try` hinzugefügt.
Wie soll das funktionieren? Anstatt die Exception auszulösen und das Programm zu beenden, wird die Fehlermeldung angezeigt, die wir angegeben haben.
value = 2_000
try:
if value > 1_000:
# raise the ValueError
raise ValueError("Please add a value lower than 1,000")
else:
print("Congratulations! You are the winner!!")
# if false then raise the value error
except ValueError as e:
print(e)
Diese Art der Ausnahmebehandlung hilft uns, uns auf die Fehler vorzubereiten, die nicht von Python abgedeckt werden und spezifisch für deine Anwendungsanforderungen sind.
Please add a value lower than 1,000
Fazit
Sowohl Unit-Tests als auch Exception-Handling sind das Herzstück der Python-Programmierung, das deinen Code produktionsreif und fehlerfrei macht. In diesem Tutorium haben wir etwas über Ausnahmen und Fehler in Python gelernt und wie man sie behandelt. Außerdem haben wir komplexe verschachtelte Try-Except-Blöcke kennengelernt und eigene Ausnahmeblöcke auf der Grundlage von Anforderungen erstellt.
Diese Werkzeuge und Mechanismen sind unverzichtbar, aber der Großteil der Arbeit wird durch einfache `try`- und `except`-Blöcke erledigt. Dabei sucht `try` nach Ausnahmen, die der Code auslöst, und `except` behandelt diese Ausnahmen.
Wenn das verwirrend ist und du nicht weißt, wo du anfangen sollst, besuche unseren Kurs Python Data Science Toolbox (Teil 1), um Scoping, Lambda-Funktionen und Fehlerbehandlung zu verstehen. Du kannst dich auch für den Berufszweig Python-Programmierer/in einschreiben, um karrierefördernde Fähigkeiten zu erwerben und ein/e professionelle/r Python-Entwickler/in zu werden.
Python-Kurse
Course
Intermediate Python
Course