← Python/Foutafhandeling
Les 3 van 8
MODULE 06 · 03◷ 24 min

De juiste fout op de juiste plek opvangen

Na deze les kun je
  • Verwachte fouten afhandelen en andere fouten doorgeven.
  • Een specifieke handler vóór een bredere categorie plaatsen.
  • Conversiefouten scheiden van fouten in een vervolgbewerking.

Een ontbrekend lijstitem kan een verwachte situatie zijn. Een tekstindex waar een getal hoort, wijst op een ander probleem. Als je beide fouten op dezelfde manier wegwerkt, wordt een programmeerfout ongemerkt een gewone uitkomst.

Vang wat je kunt herstellen

Een handler hoort bij een concrete herstelregel. IndexError kan bij een zoekfunctie betekenen dat een positie ontbreekt; daarvoor kun je bewust None teruggeven. TypeError betekent hier dat de bewerking een verkeerd soort argument kreeg, zodat diezelfde herstelregel niet vanzelf passend is.

Een niet-passende fout verlaat de functie en zoekt een handler bij de aanroeper. Dat heet een fout doorgeven. Je hoeft daarvoor geen extra code te schrijven: laat haar buiten de handlers vallen die je wel hebt gekozen.

Bekijk eerst de lijstlookup. De lege lijst krijgt een herkenbare melding, terwijl het bestaande item gewoon wordt geprint. Er is geen algemene handler nodig om het programma met deze twee afgesproken gevallen te laten werken.

Alleen een ontbrekende positie opvangen
for values, index in [([], 0), (["A"], 0)]:
    try:
        print(values[index])
    except IndexError:
        print("Buiten bereik")
Verwachte uitvoer
Buiten bereik
A

De opdracht item_or_none krijgt dezelfde beslissing, maar geeft een waarde terug in plaats van haar te printen. Een index van -1 blijft daarbij een geldige Python-index. Voeg dus geen beperking tot positieve indexen toe.

De eerste passende handler wint

Fouttypen hebben ook een indeling. LookupError is een algemener type voor onder meer IndexError en KeyError. Een handler voor LookupError past daardoor ook bij die twee specifiekere fouten.

Deze fouten vallen ook onder de brede basiscategorie Exception. Dat maakt die categorie bruikbaar aan sommige buitengrenzen, maar te breed voor veel kleine herstelregels.

Fout die ontstaatPassende categorieën uit deze les
IndexErrorIndexError, LookupError, Exception
KeyErrorKeyError, LookupError, Exception
ValueErrorValueError, Exception

Je leert later hoe je aan zo'n buitengrens een fout vastlegt en toch doorgeeft. Voorlopig kiezen we telkens de specifieke fout waarvoor de functie een herstelregel heeft.

Python bekijkt de handlers van boven naar beneden en voert de eerste passende uit. Zet daarom een specifiekere handler vóór een algemenere categorie wanneer ze verschillende uitkomsten moeten geven. Het volgende voorbeeld laat de veelgemaakte omkering zien.

De brede handler is de specifieke voor
try:
    print([][0])
except LookupError:
    print("Brede handler")
except IndexError:
    print("Specifieke handler")
Verwachte uitvoer
Brede handler

De tweede handler is hier geldig geschreven, maar krijgt deze IndexError nooit. De eerdere LookupError past al. Een extra specifieke handler onderaan repareert dus niet wat de brede handler erboven heeft onderschept.

Houd ook het try-blok klein

Zelfs het juiste fouttype kan op de verkeerde plek worden opgevangen. Stel dat je eerst een aantal omzet en daarna een meegegeven functie uitvoert. Een ValueError uit die vervolgbewerking betekent iets anders dan ongeldige getaltekst.

Vang daarom alleen de conversie af wanneer jouw herstelregel over conversie gaat. Zet de vervolgbewerking na die afhandeling, zodat haar eigen fouten zichtbaar blijven. Functies als argument ken je al uit de functiemodule; hier helpen ze de grens tussen twee verantwoordelijkheden te zien.

Jouw grenzen voor afhandeling

Bij call_or_value_error mag alleen ValueError de terugvalwaarde opleveren. lookup_label onderscheidt eerst een indexfout en daarna overige lookupfouten. Bij een geslaagde aanroep geeft die laatste functie de tekst goed terug, ongeacht de waarde van de bewerking.

apply_count zet tekst om en geeft het getal daarna aan finish. Alleen ongeldige getaltekst wordt None. Een fout uit finish moet blijven bestaan, ook als zij toevallig óók ValueError heet.

AAN DE SLAG 0/4
1

Alleen een inhoudsfout herstellen

Maak call_or_value_error(operation, default): roep de functie zonder argumenten aan en geef haar resultaat terug. Geef alleen bij ValueError de default; geef andere fouten ongewijzigd door.

2

Ontbrekende positie onderscheiden

Maak item_or_none(items, index): geef items[index] terug, of bij IndexError None. Negatieve indexen blijven geldig. Een ongeschikt indextype moet TypeError blijven geven.

3

Eerst specifiek, daarna breed

Maak lookup_label(operation): geef na een geslaagde aanroep goed terug, bij IndexError index en bij een overige LookupError lookup. Andere fouttypen gaan door naar de aanroeper.

4

De afhandelgrens klein houden

Maak apply_count(text, finish): zet text om met int en geef het getal aan finish. Geef alleen bij een conversie-ValueError None. Fouten uit finish mogen niet door die handler worden verborgen.

Onthoud dit

  • Een fout zonder passende handler gaat vanzelf door naar de aanroeper.
  • Zet specifiekere handlers vóór hun algemenere categorie.
  • Een klein try voorkomt dat een herstelregel bij de verkeerde bewerking terechtkomt.

Hierna geef je succes en opruiming eigen plaatsen met else en finally.

main.py
UitvoerPython
›
›_

Hier komt je resultaat.

Voer je code uit en ontdek
wat je hebt gemaakt.

0/4 stappen
EVEN MEEKIJKEN

Bekijk hoe het kan.

Je mag de oplossing bekijken. Deze poging telt dan niet mee als afgeronde les. Met Reset kun je daarna opnieuw zelf oefenen.