ProgrammierungBackend-Entwickler

Beschreiben Sie die Mechanismen zur Ausnahmebehandlung in Python. Wie funktioniert der Block try/except/finally, wofür ist raise gedacht und welche häufigen Fallstricke gibt es?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

In Python wird die Ausnahmebehandlung durch die Konstruktionen try/except/else/finally und den Operator raise realisiert.

try definiert den geschützten Codeblock. Wenn innerhalb dieses Blocks eine Ausnahme auftritt, wird die Kontrolle an den nächsten geeigneten except-Block übergeben. Wenn keine Ausnahme auftritt, wird der block else, falls vorhanden, ausgeführt. Der Block finally wird immer ausgeführt – unabhängig davon, ob eine Ausnahme aufgetreten ist oder nicht (zum Beispiel zum Freigeben von Ressourcen).

Der Operator raise löst eine Ausnahme explizit oder wiederholt die aktuelle (im except-Block ohne Angabe des Typs).

Beispiel:

try: x = 1 / 0 except ZeroDivisionError as e: print(f"Fehler: {e}") else: print("Es gab keinen Fehler") finally: print("Wird immer ausgeführt")

Ausgabe:

Fehler: division by zero
Wird immer ausgeführt

Feinheiten:

  • Bei verschachtelten Handlern ist die Reihenfolge der except-Blöcke wichtig: von spezifischen Typen zu allgemeineren (ansonsten werden spezifische nicht behandelt).
  • Der finally-Block kann einen erneuten Auswurf einer Ausnahme nicht verhindern (wenn im finally ein raise eingefügt wird, ist der "letzte" Fehler relevant).

Fangfrage

Frage: „Was passiert, wenn sowohl im Block try als auch im finally unterschiedliche Ausnahmen mit raise ausgelöst werden?“

Antwort: Die Ausnahme aus finally "überschreibt" die Ausnahme aus try: nach außen geht das heraus, was im finally ausgelöst wurde.

def foo(): try: raise ValueError("im try") finally: raise IndexError("im finally") try: foo() except Exception as e: print(repr(e)) # Gibt aus: IndexError('im finally')

Beispiele für reale Fehler aufgrund fehlenden Wissens über die Feinheiten des Themas


Geschichte

Im ETL-Prozess wurde im finally bedingungslos die Verbindung zur Datenbank geschlossen, aber es wurde vergessen, dass dabei im finally eine Ausnahme auftreten kann (zum Beispiel, wenn die Verbindung bereits geschlossen ist). Ergebnis – eine "versteckte" Ausnahme aus finally hat die Ausnahme aus dem Hauptcode vollständig absorbiert, was das Debugging erheblich erschwerte.


Geschichte

Es wurden Ketten mehrerer excepts verwendet: von allgemeinem except Exception über spezifischen. Infolgedessen blieben alle spezifischen excepts "tot" – niedrigstufige Ausnahmen wurden nicht einzeln gefangen, was die Behandlung spezifischer Fehler erschwerte.


Geschichte

In einem Webdienst wurde im except-Block vergessen, die Ausnahme über "raise" weiterzuleiten, während der Fehler protokolliert wurde, aber die Ausführung weiterging. Infolgedessen gingen reale Fehler "verloren", und das Programm arbeitete weiterhin mit einem inkorrekten Zustand.