Håndtere krasj

Vanligvis er krasj av programmet en bra ting, fordi vi ønsker å vite at noe er feil så fort som mulig. Men i noen tilfeller ønsker vi at programmet skal håndtere krasjen selv; dette gjelder egentlig bare når vi vet på forhånd hva slag krasj som kan oppstå, og er ikke et lurt triks å bruke dette for å skyve problemer under teppet.

Generelt vil jeg anbefale å være sparsom med bruken av try og except; hvis det kan håndteres uten på en enkel og grei måte, er det som oftest å foretrekke. Kode som er basert på mye try og except i kontrollflyten er litt mer utfordrende å feilsøke. Samtidig, dersom å bruke try/except sparer mye omstendelig kode kan det være å foretrekke likevel.



Try og except
# Håndtere en krasj
# Prøv å gi programmet noe som ikke er et tall
# Prøv å gi programmet et all som er for stort
# Programmet krasjer ikke selv om brukeren gir ugyldige svar!

animals = ["katt", "hund", "kanin", "hamster", "krokodille"]
print(f"Velg ett tall [0-{len(animals) - 1}]:")

try:
    i = int(input())
    animal = animals[i]
except:
    # Kjøres dersom try-blokken krasjet
    print("Ugyldig valg!")
else:
    # Kjøres dersom try-blokken gikk bra
    print("Gratulerer, du fikk en ny", animal)

print("Nå er programmet ferdig")

Bruk krasjhåndtering med varsomhet. Å bruke mye krasjhåndetring kan gjøre koden din litt vanskeligere å feilsøke.

# FARE!! except håndterer for mange krasjer! Vanskelig å feilsøke!
# Prøv å gi programmet en gyldig tall som input

animals = ["katt", "hund", "kanin", "hamster", "krokodille"]
print(f"Velg ett tall [0-{len(animals) - 1}]:")

try:
    i = int(input())
    animal = animal[i] # Skrivefeil! Vi VIL krasje her med NameError!
except:
    print("Ugyldig valg!") # Oops! Kommer hit selv om input er gyldig
else:
    print("Gratulerer, du fikk en ny", animal)

print("Nå er programmet ferdig")

Man bør alltid spesifisere hvilken type krasj man håndeterer.

# Håndere ulike typer feil

animals = ["katt", "hund", "kanin", "hamster", "krokodille"]
print(f"Velg ett tall [0-{len(animals) - 1}]:")

try:
    i = int(input())
    animal = animals[i]
except ValueError:
    print("Ugyldig valg, du må oppgi et tall!")
except IndexError:
    print("Tallet du oppgav er ugyldig!")
else:
    print("Gratulerer, du fikk en ny", animal)

print("Nå er programmet ferdig")

# NameError blir ikke fanget av except nå,
# så vi oppdager det nå hvis variabeler har feil navn.

Dersom man krasjer inne i en try-blokk med en feil som ikke blir håndtert, kjøres finally likevel

# Håndere ulike typer feil

animals = ["katt", "hund", "kanin", "hamster", "krokodille"]
print(f"Velg ett tall [0-{len(animals) - 1}]:")

try:
    i = int(input())
    animal = animal[i] # Skrivefeil! Vi krasjer
except ValueError:
    print("Ugyldig valg, du må oppgi et tall!")
except IndexError:
    print("Tallet du oppgav er ugyldig!")
else:
    print("Gratulerer, du fikk en ny", animal)
finally:
    # Kjøres selv om det var en krasj i try-blokken som
    # ikke ble fanget
    print("Vi er ferdig med try/except -blokken nå")

print("Nå er programmet ferdig")
Krasje på egen hånd

Kodeordet raise brukes for å krasje på egen hånd.

food = input()
if food not in ["salat", "tomat", "agurk", "paprika"]:
    raise ValueError(f"Maten '{food}' er ikke akseptabel.")

print("Takk for maten!")

Kan brukes for å gi ekstra informasjon ved krasj

def foo(i, j):
    y = j
    for x in range(i, j):
        try:
            y += abs(y/x)
        except ZeroDivisionError as err: # err variabel som 'husker' krasjen
            # Skriver ut debug-informasjon
            print("Divisjon med 0")
            print("Lokale variabler: ", locals())
            raise err # Kaster samme krasj på nytt
    return x

print(foo(-5, 10))