Tilbake
2.6
Feilsøking og debugging

2.6 Feilsøking og debugging

Lær om syntaksfeil, logiske feil og runtime-feil, print-debugging og try/except.

50 min
8 oppgaver
FeilsøkingSyntaksfeilLogisk feiltry/except
Du leser den tradisjonelle versjonen
Din fremgang i kapitlet
0 / 8 oppgaver

Feilsøking og debugging

Feil i kode er uunngåeleg. Sjølv dei mest erfarne programmerarane skriv kode med feil. Skilnaden er at erfarne programmerarar veit korleis dei skal finne og rette feila effektivt. Feilsøking (debugging) er ein viktig ferdigheit som du vil bruke like mykje som sjølve programmeringa.

Det finst tre hovudtypar feil i programmering: syntaksfeil (skrivefeil i koden), logiske feil (koden køyrer, men gir feil resultat) og køyretidsfeil (koden krasjar under køyring). I dette kapittelet lærer du å kjenne att, forstå og rette alle tre typane. Du lærer òg å bruke print-debugging og try/except for å gjere programma dine meir robuste.

Hugs: Å finne ein feil er ikkje eit teikn på at du er ein dårleg programmerar. Det er ein naturleg del av prosessen. Jo fleire feil du finn og rettar, jo betre blir du.

Debugging

Debugging (feilsøking) er prosessen med å finne, analysere og rette feil i eit dataprogram. Omgrepet stammar frå 1947 då Grace Hopper fann ei faktisk møll (bug) fanga i ei relémaskin som forårsaka feil. I dag blir «bug» brukt om alle typar programmeringsfeil, og «debugging» om prosessen med å fjerne dei. Debugging krev systematisk tenking, tolmod og evna til å lese feilmeldingar nøye.

Syntaksfeil

Syntaksfeil er «skrivefeil» i koden. Python oppdagar dei før programmet startar og viser ei feilmelding med ei pil som peikar på kvar feilen er:

# Feil 1: Manglende kolon
if alder >= 18
    print("Myndig")
# SyntaxError: expected ':'

# Feil 2: Manglende parentes
print("Hei"
# SyntaxError: unexpected EOF while parsing

# Feil 3: Feil innrykk
if True:
print("Hei")
# IndentationError: expected an indented block

# Feil 4: Manglende anførselstegn
print(Hei)
# NameError: name 'Hei' is not defined

Korleis fikse syntaksfeil:
1. Les feilmeldinga nøye - ho fortel deg kva som er gale og på kva linje
2. Sjå på linja feilmeldinga peikar på, og linja over (feilen kan vere der)
3. Sjekk etter vanlege problem: manglande kolon, parentesar, anførselsteikn og innrykk
4. Bruk ein IDE med syntaksfarging som markerer feil automatisk

Syntaksfeil er dei enklaste feila å fikse fordi Python fortel deg nøyaktig kva som er gale og kvar.

Køyretidsfeil

Køyretidsfeil oppstår når koden er syntaktisk korrekt, men noko går gale medan programmet køyrer. Python viser ein traceback (sporingsmelding) som fortel deg kva som gjekk gale:

# ZeroDivisionError - divisjon med null
tall = 10 / 0
# ZeroDivisionError: division by zero

# ValueError - ugyldig konvertering
tall = int("hei")
# ValueError: invalid literal for int() with base 10: 'hei'

# TypeError - feil type i operasjon
resultat = "5" + 3
# TypeError: can only concatenate str (not "int") to str

# IndexError - ugyldig indeks
liste = [1, 2, 3]
print(liste[5])
# IndexError: list index out of range

# NameError - variabel finnes ikke
print(udefinert_variabel)
# NameError: name 'udefinert_variabel' is not defined

Lese ein traceback

Traceback (most recent call last):
  File "program.py", line 3, in <module>
    resultat = 10 / 0
ZeroDivisionError: division by zero

Slik les du traceback:
1. Siste linje fortel deg kva feilen er: ZeroDivisionError: division by zero
2. Linja over viser koden som forårsaka feilen: resultat = 10 / 0
3. Filnamn og linjenummer fortel kvar: File "program.py", line 3

Les tracebacken frå botnen og opp for å forstå feilen raskast.

Logiske feil

Logiske feil er dei vanskelegaste å finne fordi Python ikkje gir nokon feilmelding. Koden køyrer perfekt, men resultatet er feil. Feilen ligg i logikken til programmeraren:

# Eksempel 1: Feil formel for gjennomsnittet
tall1 = 10
tall2 = 20
tall3 = 30

# FEIL: Glemte parenteser
gjennomsnitt = tall1 + tall2 + tall3 / 3  # Gir 40.0 (bare tall3 deles)

# RIKTIG:
gjennomsnitt = (tall1 + tall2 + tall3) / 3  # Gir 20.0

# Eksempel 2: Feil sammenligning i if-setning
alder = 17

# FEIL: Bruker = (tilordning) i stedet for == (sammenligning)
# if alder = 18:  # SyntaxError, men illustrerer poenget

# FEIL: Feil logikk
if alder > 18:      # Feil: 18-åringer er myndige, men > utelukker dem
    print("Myndig")

# RIKTIG:
if alder >= 18:     # Riktig: >= inkluderer 18
    print("Myndig")

# Eksempel 3: Off-by-one error (en-av-feil)
# Skrive ut tallene 1 til 10

# FEIL:
for i in range(10):     # Gir 0-9, ikke 1-10
    print(i)

# RIKTIG:
for i in range(1, 11):  # Gir 1-10
    print(i)

Korleis finne logiske feil:
- Test programmet med verdiar der du veit kva svaret skal vere
- Bruk print-debugging for å sjekke verdiar undervegs
- Gå gjennom koden steg for steg og tenk gjennom kva som skjer
- Spør deg sjølv: «Er grenseverdiane rette? Bruker eg rett operator?»

try/except
try/except er ein kontrollstruktur som lèt deg fange opp feil (exceptions) og handtere dei utan at programmet krasjar. Koden som kan forårsake ein feil blir plassert i try-blokken. Viss ein feil oppstår, hoppar Python til except-blokken der du kan handtere feilen. Viss ingen feil oppstår, blir except-blokken hoppa over. Du kan fange spesifikke feiltypar eller alle feil, og du kan ha fleire except-blokker for ulike feiltypar.

Print-debugging

Den enklaste og mest effektive feilsøkingsteknikken for nybyrjarar er å legge inn print()-setningar for å sjå kva som skjer inne i programmet:

def beregn_rabatt(pris, rabatt_prosent):
    print(f"DEBUG: pris = {pris}, rabatt_prosent = {rabatt_prosent}")

    rabatt = pris * rabatt_prosent
    print(f"DEBUG: rabatt = {rabatt}")

    ny_pris = pris - rabatt
    print(f"DEBUG: ny_pris = {ny_pris}")

    return ny_pris

resultat = beregn_rabatt(100, 20)
print(f"Pris med rabatt: {resultat}")

Køyring gir:

DEBUG: pris = 100, rabatt_prosent = 20
DEBUG: rabatt = 2000
DEBUG: ny_pris = -1900
Pris med rabatt: -1900

Vi ser at rabatt er 2000, noko som er gale. Problemet er at rabatt_prosent er 20 (heile talet), men formelen treng desimaltal (0.20). Vi må dele på 100:

rabatt = pris * rabatt_prosent / 100  # Fikset!

Tips for print-debugging:
- Merk print-setningane med «DEBUG:» slik at du lett kan finne og fjerne dei etterpå
- Skriv ut variabelverdiar på viktige punkt i koden
- Skriv ut «Kom hit!» for å sjekke om koden når bestemte stader
- Fjern eller kommenter ut debug-prints når feilen er fiksa

Feilhandtering med try/except

try/except lèt deg kontrollere kva som skjer når ein feil oppstår, i staden for at programmet krasjar:

# Uten try/except (krasjer ved ugyldig input)
# tall = int(input("Skriv et tall: "))  # Krasjer hvis brukeren skriver "hei"

# Med try/except (håndterer feilen)
try:
    tall = int(input("Skriv et tall: "))
    print(f"Du skrev {tall}")
except ValueError:
    print("Det var ikke et gyldig tall!")

Fange fleire typar feil

try:
    tall1 = int(input("Tall 1: "))
    tall2 = int(input("Tall 2: "))
    resultat = tall1 / tall2
    print(f"Resultat: {resultat}")
except ValueError:
    print("Ugyldig input! Skriv inn hele tall.")
except ZeroDivisionError:
    print("Kan ikke dele på null!")

try/except med else og finally

try:
    tall = int(input("Skriv et tall: "))
except ValueError:
    print("Ugyldig tall!")
else:
    # Kjører bare hvis ingen feil oppsto
    print(f"Tallet ditt er {tall}")
finally:
    # Kjører ALLTID, uansett om det var feil eller ikke
    print("Programmet er ferdig.")

Løkke med feilhandtering

Eit vanleg mønster er å bruke try/except i ei løkke for å spørje brukaren på nytt ved feil:

while True:
    try:
        alder = int(input("Hvor gammel er du? "))
        break  # Gyldig input, bryt ut av løkken
    except ValueError:
        print("Ugyldig! Skriv inn et helt tall.")

print(f"Du er {alder} år gammel.")

Dette er mykje betre enn å la programmet krasje. Brukaren får prøve igjen heilt til dei skriv inn gyldig input.

✏️Robust kalkulator med feilhandtering

Lag ein kalkulator som handterer alle typar feil: ugyldig input, divisjon med null, og ugyldig operator.

def hent_tall(beskjed):
    """Ber brukeren om et tall, gjentar til gyldig input."""
    while True:
        try:
            return float(input(beskjed))
        except ValueError:
            print("Ugyldig! Skriv inn et tall.")

def beregn(tall1, operator, tall2):
    """Utfører beregningen og returnerer resultatet."""
    if operator == "+":
        return tall1 + tall2
    elif operator == "-":
        return tall1 - tall2
    elif operator == "*":
        return tall1 * tall2
    elif operator == "/":
        if tall2 == 0:
            return "Feil: Kan ikke dele på null!"
        return tall1 / tall2
    else:
        return f"Feil: Ukjent operator '{operator}'"

# Hovedprogram
print("=== Robust kalkulator ===")
print("Operatorer: +, -, *, /")

tall1 = hent_tall("Første tall: ")
operator = input("Operator (+, -, *, /): ")
tall2 = hent_tall("Andre tall: ")

resultat = beregn(tall1, operator, tall2)
print(f"Resultat: {tall1} {operator} {tall2} = {resultat}")

Eksempel på kjøring med feil input:

=== Robust kalkulator ===
Operatorer: +, -, *, /
Første tall: abc
Ugyldig! Skriv inn et tall.
Første tall: 10
Operator (+, -, *, /): /
Andre tall: 0
Resultat: 10.0 / 0 = Feil: Kan ikke dele på null!

hent_tall() bruker while True med try/except for å sikre gyldig input. beregn() sjekkar for divisjon med null og ugyldig operator. Programmet krasjar aldri.

✏️Finne og rette ein logisk feil

Følgjande program skal finne det største talet i ei liste, men det fungerer ikkje rett. Finn og rett feilen.

def finn_storst(tall_liste):
    storst = 0
    for tall in tall_liste:
        if tall > storst:
            storst = tall
    return storst

print(finn_storst([-5, -2, -8, -1]))

Feilen: storst startar på 0. Viss alle tala i lista er negative, vil ingen av dei vere større enn 0, og funksjonen returnerer 0 i staden for det faktiske største talet (-1).

Print-debugging for å stadfeste:

def finn_storst(tall_liste):
    storst = 0
    print(f"DEBUG: Starter med storst = {storst}")
    for tall in tall_liste:
        print(f"DEBUG: Sjekker {tall} > {storst}? {tall > storst}")
        if tall > storst:
            storst = tall
    return storst

Ingen av dei negative tala er større enn 0, så storst blir verande 0.

Fikset versjon:

def finn_storst(tall_liste):
    storst = tall_liste[0]  # Start med det første tallet i listen
    for tall in tall_liste:
        if tall > storst:
            storst = tall
    return storst

print(finn_storst([-5, -2, -8, -1]))  # Gir -1 (riktig!)

Ved å starte med det første elementet i lista fungerer funksjonen korrekt for alle tal, inkludert negative.

Oppsummering

I dette kapittelet har du lært:

- Debugging: å finne og rette feil i kode.
- Syntaksfeil: brot på reglane i språket (f.eks. manglande kolon).
- Køyretidsfeil: feil under køyring (ZeroDivisionError, ValueError).
- Logiske feil: koden køyrer, men gir feil resultat.
- try/except: fangar opp feil så programmet ikkje krasjar.

Nøkkelomgrep


BegrepForklaring
DebuggingÅ finne og rette feil i kode
SyntaksfeilBrot på reglane i språket
KøyretidsfeilFeil som oppstår under køyring
try/exceptStruktur for å handtere feil

Oppgaver

Lett3 oppgaver
Medium3 oppgaver
Vanskelig2 oppgaver

Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.