De tre felen
Diagnosticera innan du reparerar
En läkare som ger samma behandling till alla patienter oavsett symptom är inte en bra läkare. Diagnosen måste komma före receptet. Det gäller programmering lika mycket som medicin: vet du inte vilken sorts fel du har, vet du inte heller vilket verktyg som kan lösa det.
Sekunderna före månlandningen 1969 började Apollo 11:s dator larma. Larmkoden var 1202, och den betydde att datorn hade fler uppgifter att utföra än den hann med. Farkostens programvara, byggd av ett team som Margaret Hamilton ledde, hade förberetts för exakt det: i stället för att stanna sorterade den bort de minst viktiga uppgifterna och fortsatte köra dem som styrde nedstigningen. Landningen genomfördes. Hamilton kallade arbetet software engineering vid en tid då programmering knappt räknades som ett ingenjörsyrke, och det var hon som gjorde uttrycket till ett begrepp.
Det avgörande var inte att programvaran var felfri, utan att den kunde skilja ett fel som måste stoppa allt från ett fel som gick att hantera och gå vidare från. Det är samma förmåga du bygger nu, i mindre skala.
Den här delen lär dig inget nytt fel. Du har redan stött på alla tre: syntaxfelet i Spåraren, körtidsfelet i Kraschsäkring, och logikfelet i Kartan ritas och Konsten att välja. Vad delen gör är att samla dem, ge dem namn och visa vad som skiljer dem åt.
Det låter blygsamt och är det inte. Att kunna säga vilken sorts fel man har är det som avgör vilket verktyg man tar till, och den vanan sparar mer tid än någon enskild teknik i kursen. De tre felen beter sig olika, de hittas med olika verktyg, och de kräver olika lösningar.
Syntaxfel, koden startar inte
Ett Syntaxfel Ett fel i kodens struktur som Python hittar innan programmet startar. Koden kan inte tolkas. Inget körs förrän felet är rättat. uppstår innan programmet kör en enda rad. Python läser igenom filen och kontrollerar strukturen: indrag, kolon, parenteser, citattecken. Bryter något mot grammatiken vägrar den köra.
Redo.
Kör koden. Ingenting händer, inte ens frågan efter poäng, trots att den raden står först. Det är själva signaturen för ett syntaxfel: Python vägrade innan den började. Läs felmeddelandet, lägg till det som saknas och kör igen.
Python pekar nästan alltid på rätt rad, eller raden precis efter. Se upp för det klassiska: ett saknat citattecken på rad 3 kan rapporteras som ett fel på rad 7, för det är där Python inser att något gått snett. VS Codes syntaxmarkering visar dessutom oftast felet med en röd understrykning innan du ens kör.
Körtidsfel, koden kraschar
Ett Körtidsfel Ett fel som uppstår under körning när ett undantag kastas. Koden var syntaktiskt korrekt men stötte på ett ogiltigt tillstånd. Hanteras med try/except eller rättas i källkoden. uppstår när programmet redan kör. Syntaxen var korrekt, koden startade, men sedan hände något oväntat: ett ogiltigt värde från användaren, ett namn som inte finns, två värden av typer som inte går att kombinera.
Redo.
Här händer något annat än nyss. Frågan hinner ställas, programmet är alltså igång, och först därefter kraschar det med ValueError. Byt inmatningen mot 90 och kör igen, då fungerar samma kod utan ändring.
Tracebackens sista rad talar om vilken typ av undantag det är och vad som orsakade det. Det är en riktning, inte ett svar. Verktygen är tracebacken för att identifiera felet och try/except för att hantera det, precis det du gjorde i Kraschsäkring.
Logikfel, koden kör men gör fel
Det här är den farligaste kategorin. Programmet kör. Python klagar inte. Men resultatet är fel, för logiken i koden stämmer inte med logiken du menade.
Redo.
Kör koden. Eleven har 95 poäng och får betyget C. Ingen krasch, inget felmeddelande, bara ett svar som är fel. Flytta villkoren så att det strängaste kravet prövas först och kör igen.
Python såg korrekt syntax och körde precis det du skrev. Problemet var att det du skrev inte var det du menade, och den skillnaden är osynlig för datorn.
Det är samma bokstavlighet som i Noll eller ett, fast från sin obehagliga sida. Där räddade den dig: Print var fel och du fick veta det direkt. Här finns ingen sådan hjälp, eftersom allt du skrev var giltigt. Datorn kan säga ifrån när du skriver något den inte förstår, aldrig när du skriver något den förstår men du inte menade.
Tre frågor när du fastnar
De tre felkategorierna beskriver när något går snett. Men när du sitter riktigt fast är problemet ofta inte felet i sig, utan att du inte vet vilken sorts problem du har. Tre frågor, ställda i den här ordningen, sorterar det:
- Förstår jag vad koden ska göra? Om nej: gå tillbaka till uppgiften, rita ett flödesschema, förklara problemet för en klasskompis. Det här är inget fel i koden, det är ett fel i förståelsen, och utan den leder alla verktyg fel.
- Startar och kör koden? Om nej: läs tracebacken.
- Ger koden rätt resultat? Om nej: öppna debuggern.
Det är inte tre listor att memorera, det är tre frågor att ställa. Den första är viktigast: många timmar går förlorade i jakt på syntaxfel och logikfel när det egentliga problemet är att man inte förstår vad koden ska åstadkomma.
Uppgift: Felsök någon annans kod
Nu är det du som är felsökaren, och koden är inte din. Programmet nedan ska räkna ut klassens medelpoäng och sätta ett betyg. Det innehåller tre fel, ett av varje sort.
Skapa filen felsokning.py och klistra in koden:
poäng = [95, 72, 48]
summa = 0
for p in poäng
summa += p
medel = summa / len(poäng)
print("Medelpoäng: " + medel)
if medel >= 50:
betyg = "C"
elif medel >= 70:
betyg = "B"
elif medel >= 90:
betyg = "A"
print(f"Klassens betyg: {betyg}") Kör programmet. Skriv ned vad som händer, vilken feltyp det är, och rätta felet.
Kör igen. Nu dyker nästa fel upp. Skriv ned feltypen och vilket undantag tracebacken namnger, och rätta det.
Kör igen. Nu kör programmet hela vägen, men svaret är fel. Kontrollräkna för hand vad medelpoängen blir och vilket betyg den borde ge. Använd debuggern för att se vilken gren koden faktiskt tar.
Skriv överst i filen en kommentar med tre rader, en per fel: feltypen, hur du upptäckte den och vilket verktyg som avslöjade den.
Gå till Source Control-panelen i VS Code, stagea filen, skriv ett meningsfullt commit-meddelande och pusha.
Vad händer om
Du försöker fånga det tredje felet med try/except ValueError. Fungerar det? Förklara varför eller varför inte.
Motivera & reflektera
Felen dök upp i en bestämd ordning, och du kunde inte hitta det tredje förrän de två första var lösta. Motivera varför ordningen blev just den, och vad det säger om i vilken ordning man bör felsöka.