ProgrammatieBackend ontwikkelaar

Beschrijf de mechanismen voor exception handling in Python. Hoe werkt het try/except/finally-blok, waarvoor is raise nodig, en welke valkuilen komen vaak voor?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

In Python wordt exception handling geïmplementeerd via de constructies try/except/else/finally en de operator raise.

try definieert het beschermde codeblok. Als er binnen dit blok een uitzondering optreedt, wordt de controle overgedragen aan het dichtstbijzijnde geschikte except-blok. Als er geen uitzondering is, wordt het else-blok uitgevoerd, indien aanwezig. Het finally-blok wordt altijd uitgevoerd, ongeacht of er wel of geen uitzondering was (bijvoorbeeld om middelen vrij te geven).

De operator raise roept expliciet een uitzondering op of herhaalt de huidige (in het except-blok zonder typevermelding).

Voorbeeld:

try: x = 1 / 0 except ZeroDivisionError as e: print(f"Fout: {e}") else: print("Er was geen fout") finally: print("Wordt altijd uitgevoerd")

Uitvoer:

Fout: division by zero
Wordt altijd uitgevoerd

Fijnere details:

  • Bij geneste exception handlers is de volgorde van except belangrijk: van specifieke types naar algemenere (anders worden specifieke niet behandeld).
  • Het finally-blok kan een herhaalde uitzondering niet voorkomen (als je een raise in een finally plaatst, is de meest "recente" fout van toepassing).

Misleidende vraag

Vraag: "Wat gebeurt er als er zowel in het try-blok als in het finally een raise op verschillende uitzonderingen wordt aangeroepen?"

Antwoord: De uitzondering uit finally "overschrijft" de uitzondering uit try: wat naar buiten komt is wat in finally is gegooid.

def foo(): try: raise ValueError("in try") finally: raise IndexError("in finally") try: foo() except Exception as e: print(repr(e)) # Geeft: IndexError('in finally')

Voorbeelden van echte fouten door onwetendheid over de fijnere details van het onderwerp


Verhaal

In een ETL-proces werd de verbinding met de database altijd zonder uitzondering gesloten in het finally-blok, maar ze vergaten dat er in finally ook een uitzondering kan optreden (bijvoorbeeld als de verbinding al is gesloten). Het resultaat was dat een "verborgen" uitzondering uit finally de uitzondering uit de hoofdcode volledig opslokte, wat het debuggen bemoeilijkte.


Verhaal

Ze gebruikten ketens van meerdere except-blokken: van het algemene except Exception boven de specifieken. Als gevolg hiervan bleven alle specifieke except-blokken "dood"; lagere uitzonderingen werden niet apart opgevangen, wat het omgaan met specifieke fouten bemoeilijkte.


Verhaal

In een webservice vergaten ze in het except-blok de uitzondering verder door te geven met "raise", logden de fout maar lieten de uitvoering verdergaan. Hierdoor "gingen" echte fouten "verloren", terwijl het programma doorging met een onjuiste toestand.