Felhantering och undantag

Göra program robusta mot körtidsfel med hjälp av try-except-block.

Ca 60 min · del av Programmering i Python

Begrepp i lektionen

  • try
  • except
  • finally
  • raise
  • Exception

Efter denna lektion kommer du att kunna skriva robusta Python-program som hanterar körtidsfel elegant med try-except-block, kasta egna undantag och förstå programmets flöde vid fel.

Vad är undantag och varför behövs felhantering?

När du skriver kod i Python kan två huvudtyper av fel uppstå: syntaktiska fel och körtidsfel (kallade *exceptions* eller *undantag*).

Ett syntaktiskt fel innebär att koden bryter mot Pythons grammatska regler och programmet kan inte starta alls. Ett körtidsfel uppstår däremot när koden är korrekt skriven syntaktiskt, men något går fel medan programmet körs. Det kan till exempel hända om användaren matar in text när ett tal förväntas, om programmet försöker dela ett tal med noll, eller om en fil som ska öppnas inte existerar.

När ett körtidsfel inträffar utan felhantering avbryts programmet omedelbart och kraschar med ett felmeddelande (en så kallad *Traceback*). I verkliga applikationer är detta oacceptabelt – ett användargränssnitt ska inte bara stängas ner utan varning.

Genom att använda felhantering kan vi fånga dessa undantag i stället för att låta dem krascha programmet. Vi kan ge användaren ett förklarande meddelande, be om ny inmatning eller städa upp resurser snyggt innan programmet avslutas.

Grundläggande felhantering med try och except

För att hantera kriser i koden använder vi ett try-except-block. Principen är enkel: koden vi vill testa placeras i `try`-blocket, och koden som ska köras om ett fel inträffar placeras i `except`-blocket.

Exempel:

python

try:

tal = int(input("Ange ett heltal: "))

resultat = 100 / tal

print("Resultat:", resultat)

except ValueError:

print("Du måste mata in ett giltigt heltal!")

except ZeroDivisionError:

print("Du kan inte dela med noll!")

Lägg märke till att vi specificerar exakt vilket undantag vi vill fånga upp (`ValueError`, `ZeroDivisionError`). Om ett `ValueError` uppstår (t.ex. om användaren skriver 'tio') hoppar Python direkt ur `try`-blocket till motsvarande `except`-block. Om koden körs utan fel hoppas alla `except`-block över helt.

Utökad felhantering: else och finally

Python har två valfria block som kan läggas till i en try-except-struktur: else och finally.

  • else: Körs BARA om koden i `try`-blocket genomfördes helt utan att några fel uppstod.
  • finally: Körs ALLTID, oavsett om ett fel uppstod, om felet fångades, eller om koden kördes helt felfritt. Det används oftast för städuppgifter, såsom att stänga en öppnad fil eller koppla från en databas.

Fullständig struktur:

python

try:

fil = open("data.txt", "r")

innehall = fil.read()

except FileNotFoundError:

print("Filen kunde inte hittas.")

else:

print("Filen lästes in framgångsrikt!")

print("Längd:", len(innehall))

finally:

print("Städar upp... stänger filen om den öppnats.")

Genom att separera koden på detta sätt hålls `try`-blocket så kort som möjligt (bara koden som kan orsaka felet), medan `else` tar hand om logiken som beror på att `try` lyckades.

Kasta egna undantag med raise

Ibland vill du att ditt eget program ska generera ett fel om ett visst villkor inte uppfylls. Det gör du med nyckelordet raise.

Att kasta (eller 'resa') ett undantag är användbart vid validering av indata eller i egna funktioner när ett ogiltigt tillstånd uppstår.

Exempel:

python

def saett_alder(alder):

if alder < 0:

raise ValueError("Ålder kan inte vara ett negativt tal!")

print("Ålder inställd till:", alder)

try:

saett_alder(-5)

except ValueError as e:

print("Fel inträffade:", e)

Alla undantag i Python ärver från den inbyggda klassen `Exception`. Du kan fånga det faktiska felobjektet genom att skriva `except ValueError as e`, där `e` innehåller felmeddelandet som skickades med.

Hela kursen