söndag 9 september 2012

Fel och undantag

Det finns tre grundtyper av fel i programmeringssammanhang:
  • Syntax-fel: Fel i källkoden pga stavfel eller felaktig satsbyggnad
  • Buggar: Fel i källkoden så att programmet inte uppför sig som förväntat
  • Undantag (eng. Exceptions) Fel av typen division med noll, inmatning av text när en siffra förväntas mm.
Syntaxfelen brukar upptäckas av skalet du använder för att skriva ditt program. Buggar är upp till dig som programmerare att leta efter och rätta. För små program är det ofta enkelt att finna dem men för större kan det vara mycket svårt.

Undantag kan även beskrivas som förväntade problem. Sådant som du när du programmerat räknar med kan hända. Till exempel att någon råkar trycka ENTER istället för att skriva in ett tal. Det är att hantera undantag vi ska titta på här.

try-satsen

Satsen try används för att hantera förväntade problem. De består av två delar try och except.  Se nedanstående exempel:

Övning 1.15
Skriv följande program som hanterar division med noll och testa funktionen

a=float(input("nämnaren="))
try :
    print(100/a)
except ZeroDivisionError :
    print("Division med noll")
print("Tack för mig")

Hur det fungerar:
  • Först utförs de indragna satserna mellan try och except.
  • Om inget undantag inträffar hoppas de indragna satserna efter except över och programmet går vidare vid print("Tack för mig") .
  • Om ett undantag inträffar vid någon av satserna mellan try och except så hoppar programmet direkt till except. Där kontrolleras om undantaget är av den klass (typ) som beskrivs av nyckelordet ZeroDivisionError. Om så är fallet utförs de indragna satserna efter except. Texten "Division med noll" skrivs ut. Sedan fortsätter programmet till sitt slut.
  • Om ett undantag inträffar av en annan klass än ZeroDivisionError kommer programmet att hantera detta på standardsätt. Alltså programmet avslutas med ett felmeddelande.


Övning 1.16
Kör programmet i övning 1.15 och skriv in en bokstav istället för ett tal.

Notera att programmet nu avslutas med ett felmeddelande och sista raden inte körs. Du har nu skapat ett icke hanterat undantag (eng. unhandled exception).

Några undantagsklasser

Det finns en stor mängd färdigdefinierade undantag i Python. De är också ordnade i en hierarki med vissa undantag som är generella och täcker in flera underklasser.

Klass Beskrivning
Exception Huvudklassen för alla undantag. Används med försiktighet för att fånga upp undantag. Använd i första hand mer specifika klasser i stället.
IOError Undantag vid tex. läsning av och skrivning till filer.
IndexError Undantag vid hantering av listor och dylikt. Mer om detta senare i kursen
TypeError Undantag då typen är fel för operationen/fuktionen.  Tex: print("a"+2).
ValueError Undantag vid ogiltigt värde. Tex. math.sqrt(-2)
Även försök att omvandla en sträng bokstäver till tal med float() och int(). Se nedan övning 17
ZeroDivisionError Undantag vid division med noll.

Det går att ha flera olika klasser av undantag listade efter except. Man sätter de då inom parentes och med komma mellan dem. Till exempel kan det ibland vara bra att hantera matematiska fel med:

except (ValueError, ZeroDivisionError) :


Överkurs: Läs mer om undantag och hierarkin. Följ länkarna i texten ovanför tabellen.

Överkurs: Det går att ha flera except i en och samma try-sats för att hantera olika undantag. Läs om detta här.

Övning 1.17
Denna övning visar hur man skriver ett program som hanterar inmatning så att frågan upprepas tills användaren matar in korrekt datatyp. Skriv och testa.

while True :
    try :
        a=float(input("Skriv en siffra "))
        break
    except ValueError :
        print("Ooops! Ej ett tal")
print("Du skrev " + str(a))

Programmet snurrar i while-loopen om det blir ett undantag i tilldelningen av a. Om tilldelningen sker korrekt når programmet break-satsen och hoppar ur loopen  till sista raden.

Uppgift 1.5
Skriv om inlämningsuppgift 1.2, andragradsekvationsprogrammet, så att det hanterar felaktiga värden vid inmatning (så som text eller bara ENTER) samt använder undantag istället för if-sats för att hantera negativa rötter.

Uppgift 1.6
Då man ska mata in många värden är det extra viktigt att använda undantagshantering. Ingen vill mata in 143 värden och sedan kraschar programmet pga att man råkar trycka fel vid det 144...
Skriv om uppgift 1.4 så att felaktiga inmatningar hanteras. Tips: det går att utnyttja den oändliga loopen som redan finns för att effektivt genomföra detta.

Inga kommentarer:

Skicka en kommentar