Programmering nivå 2
Kap 1.6 – Undantagshantering
Lär dig hantera fel så att programmet kan fortsätta på ett kontrollerat sätt.
Mål med lektionen
När du har arbetat klart med denna lektion ska du:
- förstå vad ett undantag är
- kunna använda
tryochexcept - förstå varför
ValueErrorofta uppstår vid inmatning - kunna låta användaren försöka igen vid fel inmatning
- kunna bygga mer robusta program
Vad är ett undantag?
Ett undantag är ett fel som uppstår medan programmet körs. Det kan till exempel hända när användaren skriver text där programmet förväntar sig ett tal.
Utan undantagshantering avbryts programmet direkt. Med undantagshantering kan programmet fånga felet, visa ett begripligt meddelande och fortsätta.
Exempel utan undantagshantering
Det här programmet fungerar om användaren skriver ett heltal:
age = int(input("Hur gammal är du? "))
print(age + 5)
Men om användaren skriver hej kraschar programmet, eftersom int("hej") inte
går att göra om till ett heltal.
Exempel med try och except
try:
age = int(input("Hur gammal är du? "))
print(age + 5)
except ValueError:
print("Du måste skriva ett heltal.")
Steg för steg
trybetyder: försök köra den här koden.- Programmet frågar efter ålder och försöker göra om svaret till ett heltal.
- Om det fungerar körs
print(age + 5). - Om användaren skrev något som inte kan bli ett heltal uppstår
ValueError. except ValueErrorfångar just det felet och skriver ut ett eget felmeddelande.
Varför skriver man vilken typ av fel som ska fångas?
Det är bättre att skriva except ValueError än bara except. Då fångar du det
fel du faktiskt förväntar dig, i stället för att råka dölja andra problem i koden.
Låta användaren försöka igen
Undantagshantering används ofta tillsammans med en loop. Då kan programmet fråga igen tills användaren skriver något giltigt.
while True:
try:
age = int(input("Hur gammal är du? "))
print(age + 5)
break
except ValueError:
print("Fel inmatning, försök igen.")
Steg för steg: loop med felhantering
while Truegör att programmet fortsätter fråga.try-delen testar om inmatningen kan göras om till ett heltal.- Om det fungerar skrivs resultatet ut.
breakavslutar loopen när programmet har fått ett giltigt värde.- Om inmatningen är fel körs
except, och loopen börjar sedan om.
Robusta program
Ett robust program klarar vanliga fel utan att krascha. Det betyder inte att programmet ignorerar fel, utan att det hanterar dem på ett tydligt sätt.
Här hanteras både fel datatyp och division med noll:
while True:
try:
number = int(input("Skriv ett tal: "))
if number == 0:
print("Du kan inte dela med 0.")
else:
print(100 / number)
break
except ValueError:
print("Fel inmatning, försök igen.")
Interaktiv övning: undantagshantering
Testa hur programmet reagerar på giltig och ogiltig inmatning. Skriv till exempel
17, hej eller 0.
Prova till exempel att:
- välja
Ålder + 5och skrivahej - välja
Ålder + 5och skriva17 - välja
100 delat med taloch skriva0
Programmering 2-koppling: här kombineras inmatning, typomvandling, villkor, loop och undantagshantering till ett mer stabilt program.
Öva själv
Övning 1: Dubbla ett heltal
Skriv ett program som frågar användaren efter ett heltal och skriver ut talet gånger två.
Använd try och except ValueError för att visa meddelandet
"Du måste skriva ett heltal." om inmatningen inte kan omvandlas till ett heltal.
Testa programmet med
6, vilket ska ge12.-4, vilket ska ge-8.hej, vilket ska ge felmeddelandet.
Fundera: Vilken rad i try-blocket kan
orsaka ValueError?
När du har försökt själv: visa lösningsförslaget till övning 1 på GitHub.
Övning 2: Dividera 100 med ett tal
Skriv ett program som frågar efter ett heltal och skriver ut 100 dividerat med
talet. Fånga felaktig text med except ValueError. Använd ett villkor för att skriva
"Du kan inte dela med 0." om användaren skriver 0.
Testa programmet med
4, vilket ska ge25.0.0, vilket ska ge meddelandet om division med noll.fem, vilket ska ge ett tydligt felmeddelande.
Fundera: Varför kontrolleras talet 0 med
ett villkor i stället för att programmet försöker utföra divisionen?
När du har försökt själv: visa lösningsförslaget till övning 2 på GitHub.
Övning 3: Fråga tills svaret är giltigt
Skriv ett program som använder while True, try och
except ValueError för att fortsätta fråga efter ett heltal tills användaren skriver
ett giltigt värde. Skriv ut talet och avsluta loopen med break när inmatningen är
giltig.
Testa programmet med
- Ett giltigt heltal direkt.
hej, därefter3.5och till sist8.
Fundera: Varför ska break bara köras efter
att omvandlingen till heltal har lyckats?
När du har försökt själv: visa lösningsförslaget till övning 3 på GitHub.
Övning 4: Kontrollera en giltig ålder
Skriv ett program som fortsätter fråga efter en ålder tills användaren skriver ett heltal som
är större än eller lika med 0. Text och decimaltal ska hanteras med
except ValueError. Negativa heltal ska hanteras med ett vanligt villkor och ett
eget meddelande.
Testa programmet med
Anna, därefter-2och till sist20.0, som ska godkännas direkt.
Fundera: Varför orsakar ett negativt heltal inte
ValueError?
När du har försökt själv: visa lösningsförslaget till övning 4 på GitHub.
Övning 5: Funktion för säker inmatning
Svårare övning: Här kombinerar du en funktion,
undantagshantering, en loop och return.
Skriv funktionen get_valid_number(). Funktionen ska fråga efter ett heltal tills
inmatningen är giltig och sedan returnera talet. Anropa funktionen tre gånger från
huvudprogrammet och skriv ut summan av de tre talen.
Testa programmet med
2,4och6, vilket ska ge summan12.- Minst en felaktig text före ett av de giltiga talen.
Fundera: Hur gör funktionen att du slipper skriva samma felhantering tre gånger?
När du har försökt själv: visa lösningsförslaget till övning 5 på GitHub.
Övning 6: Robust miniräknare
Svårare övning: Här kombinerar du funktioner, returvärden, en meny, loopar, villkor och undantagshantering.
Skapa en miniräknare med en meny som har alternativen 1. Addera,
2. Dividera och 3. Avsluta. Menyn ska visas i en
while True-loop. Vid addition eller division ska programmet fråga efter två heltal
och använda try och except ValueError så att felaktig inmatning inte
kraschar programmet. Kontrollera division med noll med ett villkor. Valet 3 ska
avsluta programmet med break, och andra menyval ska ge ett tydligt felmeddelande.
Testa programmet genom att
- addera
4och7. - dividera
20med4. - försöka dividera med
0. - skriva text när programmet frågar efter ett tal.
- välja ett ogiltigt menyalternativ och därefter avsluta med
3.
Fundera: Varför ligger menyn utanför
try-blocket medan omvandlingen av talen ligger inuti?
När du har försökt själv: visa lösningsförslaget till övning 6 på GitHub.
Reflektion
- Vad är skillnaden mellan ett syntaxfel och ett fel som uppstår när programmet körs?
- Varför är det bättre att ge användaren ett tydligt felmeddelande än att låta programmet krascha?
- När kan
tryochexceptgöra ett program lättare att använda?