Przejdź do treści
Strona główna » Kurs Python: obsługa wyjątków

Kurs Python: obsługa wyjątków

Czym są wyjątki w Pythonie?

Błędy w Pythonie dzielimy na dwa rodzaje, tj. błędy składniowe i wyjątki. Błędy składniowe to problemy w programie, z powodu których program zatrzyma wykonywanie. Z kolei wyjątki, występują w określonych okolicznościach działania programu i zmieniają jego normalny przebieg.

Różnica pomiędzy błędem składniowym a wyjątkiem

Błąd składniowy, jak sama nazwa wskazuje, to błąd związany z zapisem w kodzie sprzecznym ze składnią Pythona. Prowadzi to do zakończenia programu. Weźmy poniższy przykład:

Python
i = 0
while i < 100:
  print(i)
  i ++= 1

Widzimy, że w linii 4 znajduje się błąd składniowy, ponieważ zamiast i += 1 programista zapisał błędnie i ++= 1. W efekcie tego błędu, po uruchomieniu programu zobaczymy błąd:

SyntaxError: invalid syntax

Wyjątki są zgłaszane, gdy działanie programu powoduje błąd, jednak nie jest on spowodowany błędem składniowym. Przykładem może być próba otwarcie nieistniejącego pliku:

Python
fh = open("testfile", "r")

Zapis w kodzie jest prawidłowy, jednak gdy plik nie istnieje, to podczas uruchomienia programu otrzymamy:

FileNotFoundError: [Errno 2] No such file or directory: 'testfile'

Wyjątki zgłaszane przez program możemy obsługiwać, dzięki czemu program jest odporny, na różnego rodzaju sytuacje niepożądane.

Zgłaszanie wyjątków i łapanie (try i except)

Instrukcje try i except służą do przechwytywania i obsługi wyjątków w Pythonie. Podstawowa składnia bloku try...except wygląda następująco:

Python
try:
  # kod, który może rzucać wyjątek
except:
  # kod, który się uruchamia, gdy wyjątek wystąpi

Weźmy przykład dzielenia dwóch liczb:

Python
wynik = licznik/mianownik

Jak wiadomo, operacja dzielenia przez 0 nie jest możliwa. Pomimo tego, że składnia kodu jest prawidłowa, to po uruchomieniu programu dostaniemy:

ZeroDivisionError: division by zero

Program możemy zabezpieczyć przed niepożądaną operacją dzielenia przez 0 stosując blok try...catch w następujący sposób:

Python
try:
    licznik = 5
    mianownik = 0

    wynik = licznik/mianownik

    print(wynik)
except:
    print("Błąd. Nie można dzielić przez 0")

Dzięki temu działanie programu nie zostanie zatrzymane. Zamiast błędu otrzymamy komunikat “Błąd. Nie można dzielić przez 0”.

Rodzaje wyjątków w Pythonie

W Pythonie istnieje kilka wbudowanych typów wyjątków. Oto niektóre z nich:

  • KeyError: wyjątek jest zgłaszany, gdy w słowniku nie znaleziono klucza.
  • ValueError: wyjątek jest zgłaszany, gdy funkcja lub metoda jest wywoływana z nieprawidłowym argumentem, lub danymi wejściowymi.
  • TypeError: wyjątek jest zgłaszany, gdy operacja lub funkcja zostanie zastosowana do obiektu niewłaściwego typu.

Pełną lista wbudowanych wyjątków znajdziemy pod adresem:

https://docs.python.org/3/library/exceptions.html

Łapanie określonych wyjątków w Pythonie

W poniższym kodzie zaimplementowano dwa bloki catch. Pierwszy z nich przechwytuje wyjątek ZeroDivisionError, a drugi IndexError.

Python
try:
    licznik = 5
    liczby = [1, 4, 1, 4]
    mianownik = liczby[2]
    print(licznik/mianownik)
    mianownik = liczby[5]
    print(licznik/mianownik)

except ZeroDivisionError:
    print("Błąd. Nie można dzielić przez 0")
    
except IndexError:
    print("Przekroczono rozmiar listy")

Ponieważ w linii 6 program odwołuje się do elementu o indeksie 5, który nie istnieje, zostanie rzucony wyjątek IndexError, który zostanie przechwycony przez odpowiedni blok catch. W efekcie po uruchomieniu otrzymamy:

5.0
Przekroczono rozmiar listy

Blok try…finally

W Pythonie blok finally jest wykonywany zawsze, niezależnie od tego, czy wyjątek wystąpił, czy nie.

Python
try:
    licznik = 5
    mianownik = 0

    wynik = licznik/mianownik

    print(wynik)
except:
    print("Błąd. Nie można dzielić przez 0.")
finally:
    print("To jest blok finally.")

Wynik:

Błąd. Nie można dzielić przez 0.
To jest blok finally.