2.25. Fouten afhandelen¶
De meeste runtimeproblemen in Python verschijnen als uitzonderingen – een benoemde, gestructureerde manier om te melden dat er iets misging. ValueError, TypeError, KeyError, OSError, MemoryError zijn allemaal voorbeelden; elk is een klasse, en het opwerpen van zo’n uitzondering stopt de huidige aanroep en zoekt naar een afhandelaar in de omringende code.
2.25.1. try / except¶
Wikkel een codeblok in try om elke uitzondering die het opwerpt op te vangen:
try:
n = int(input_text)
except ValueError:
n = 0
Als de conversie int(...) mislukt, springt de besturing naar het except-blok in plaats van de fout verder te verspreiden. Als input_text een geldige gehele-getallenstring was, wordt het except-blok overgeslagen.
Een enkele try kan meerdere except-blokken hebben, elk dat een ander soort fout opvangt:
try:
value = data[key]
except KeyError:
value = None
except TypeError:
value = -1
Python vergelijkt in volgorde; de eerste waarvan de uitzonderingsklasse past, handelt het probleem af. Het opvangen van Exception (de basisklasse voor bijna alles) handelt elke fout af; reserveer dat voor de buitenste laag van een programma waar het alternatief een crash is.
Waarschuwing
Een kale except: (geen klasse na het sleutelwoord) vangt ook KeyboardInterrupt op – de uitzondering die de IDE stuurt wanneer je op de stop-knop drukt om een draaiend script te onderbreken. Een lus die in een kale except: pass is gewikkeld, slikt de onderbreking in en blijft draaien, waardoor er geen manier is om het script te stoppen behalve een stroomcyclus.
Geef de voorkeur aan except Exception: boven een kale except: wanneer je werkelijk breed moet opvangen. KeyboardInterrupt erft van BaseException, niet van Exception, dus bij except Exception: blijft de stop-knop werken.
2.25.1.1. De uitzondering inspecteren¶
Om het bericht te lezen dat aan een uitzondering is gekoppeld, benoem je deze met as:
try:
f = open("data.txt")
except OSError as e:
print("could not open file:", e)
De variabele die met as is gebonden, is alleen geldig binnen het except-blok.
2.25.2. else en finally¶
Een try-blok heeft twee optionele extra’s.
else wordt alleen uitgevoerd wanneer de try voltooide zonder een uitzondering op te werpen:
try:
value = compute()
except ValueError:
print("bad input")
else:
print("got", value)
Door “wat te doen wanneer het werkte” in else te plaatsen, blijft het try-blok smal – alleen de regel die kan mislukken hoort in try.
finally wordt aan het einde uitgevoerd wat er ook gebeurt – of de try nu slaagde, opwierp en werd afgehandeld, of opwierp en op het punt staat zich te verspreiden:
try:
do_work()
finally:
cleanup()
finally wordt altijd uitgevoerd. else wordt alleen uitgevoerd op het niet-uitzonderingspad.¶
Geef voor de meeste verkrijg/vrijgeef-patronen de voorkeur aan een contextmanager boven een try / finally-paar – de bron beheert zelf zijn eigen opruiming.
2.25.3. Veelvoorkomende ingebouwde uitzonderingen¶
Een korte lijst van de uitzonderingen die je vaak zult tegenkomen:
ValueError– juist type, verkeerde waarde (bytes([300])– 300 is het juiste type, maar valt buiten het geldige bytebereik van 0..255).TypeError– helemaal het verkeerde type (len(42)).IndexError– index voorbij het einde van een reeks.AttributeError– toegang tot een attribuut dat niet bestaat ("abc".foo).OSError– een fout in het bestandssysteem of de I/O.MemoryError– de heap is op. Op een geheugenbeperkte runtime kan dit tijdens normaal gebruik gebeuren – niet alleen in pathologische gevallen.