← Lekcje
Python · lekcja 16

Błędy i wyjątki: try i except

  1. Trzy rodzaje błędów: składni, wykonania, logiczny
  2. Jak czytać czerwony komunikat i skąd wiadomo, co się stało
  3. try i except: program nie przerywa się na byle czym
  4. Pętla „pytaj, aż podasz liczbę”
Rozgrzewka · 3 minuty

Co pamiętacie z lekcji 15?

  1. Co robi zapis with open("notes.txt", encoding="utf-8") as f:?
  2. Czym różnią się tryby "r", "w" i "a" w funkcji open?
  3. Jak policzyć, ile linii ma otwarty plik?
Część 1 · Rodzaje błędów

Trzy sposoby, na jakie program może zawieść

Błąd składni zapis niezgodny z regułami while True print("Ala") SyntaxError program nie rusza wcale Błąd wykonania zapis dobry, dane złe int("szesnascie") ValueError rusza i przerywa się w locie Błąd logiczny zła kolejność działań 2 + 8 / 2 daje 6.0 bez komunikatu działa i podaje zły wynik

Błąd wykonania nazywamy wyjątkiem: sytuacją, której program nie umie wykonać, choć zapisany jest poprawnie. Średnia z 2 i 8 to (2 + 8) / 2, czyli 5.0. Bez nawiasu Python liczy 2 + 8 / 2 i daje 6.0, bez żadnego ostrzeżenia.

docs.python.org, The Python Tutorial, rozdz. 8.1 (Syntax Errors) i 8.2 (Exceptions) · Podręcznik Informatyka na czasie 2 (Nowa Era), s. 97 (błąd składniowy, rys. 6.5) i s. 98 (ramka „Warto wiedzieć”, błąd logiczny)
Część 1 · Komunikat o błędzie

Czerwony napis czyta się od dołu

Traceback (most recent call last):
  File ".../age.py", line 2, in <module>
    age = int(input())
          ^^^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'szesnascie'
  • 1. linia zapowiada: dalej jest ślad błędu.
  • 2. linia to plik i numer linii, w której program się zatrzymał.
  • 3. i 4. pokazują tę linię kodu i strzałkami miejsce błędu.
  • Ostatnia linia jest najważniejsza: ValueError to typ wyjątku, a po dwukropku opis po angielsku.

W praktyce: strzałki pokazują miejsce, w którym interpreter wykrył błąd, a nie zawsze to, które trzeba poprawić. Przy brakującym dwukropku po while True strzałki wskazują dopiero na print w następnej części linii.

docs.python.org, The Python Tutorial, rozdz. 8.2 (Exceptions) · ciekawostka: rozdz. 8.1 (Syntax Errors)
Część 1 · Typy wyjątków

Pięć nazw, które zobaczycie najczęściej

Typ wyjątkuKiedy leciPrzykładKoniec komunikatu
ValueErrorzła wartość w dobrym typieint("abc")invalid literal for int() with base 10: 'abc'
ZeroDivisionErrordzielenie przez zero7 / 0division by zero
TypeErrordziałanie na złych typach"2" + 2can only concatenate str (not "int") to str
IndexErrorindeks poza listą[10, 20, 30][5]list index out of range
FileNotFoundErrornie ma takiego plikuopen("brak.txt")No such file or directory: 'brak.txt'
docs.python.org, The Python Tutorial, rozdz. 8.2 (Exceptions)
Część 2 · try i except

Dwie drogi zamiast czerwonego napisu

Zapis try („spróbuj”) mówi: wykonaj te instrukcje, a jeśli poleci wyjątek wymieniony po except („w razie”), zrób zamiast tego blok ratunkowy. Program nie przerywa się, tylko leci dalej.

blok try: tu może pójść coś nie tak czy poleciał ValueError? nie tak cały blok try się wykonuje blok except pominięty reszta try pominięta wykonuje się blok except program leci dalej
docs.python.org, The Python Tutorial, rozdz. 8.3 (Handling Exceptions)
Część 2 · Kilka except

Jeden try, osobna odpowiedź na każdy wyjątek

print("Podaj dzielną:")
try:
    a = int(input())
    print("Podaj dzielnik:")
    b = int(input())
    print("Wynik:", a / b)
except ValueError:
    print("To nie jest liczba całkowita.")
except ZeroDivisionError:
    print("Przez zero nie dzielimy.")
WpisanoNa ekranie
10 i 4Wynik: 2.5
10 i 0Przez zero nie dzielimy.
10 i „dwa”To nie jest liczba całkowita.

Python sprawdza bloki except po kolei i wykonuje pierwszy pasujący. W żadnym z trzech przypadków program się nie przerywa.

docs.python.org, The Python Tutorial, rozdz. 8.3 (Handling Exceptions)
Część 2 · Pytaj aż do skutku

Pętla, która nie odpuszcza

while True:
    print("Podaj swój wiek:")
    try:
        age = int(input())
        break
    except ValueError:
        print("To nie jest liczba. Spróbuj jeszcze raz.")

print("Za rok będziesz mieć", age + 1)
Podaj swój wiek:
szesnascie
To nie jest liczba. Spróbuj jeszcze raz.
Podaj swój wiek:
16.5
To nie jest liczba. Spróbuj jeszcze raz.
Podaj swój wiek:
16
Za rok będziesz mieć 17

Zapis 16.5 też daje ValueError: funkcja int przyjmuje wyłącznie liczby całkowite.

W praktyce: przerwanie programu klawiszami Ctrl i C to również wyjątek, o nazwie KeyboardInterrupt. Dzięki temu program z pętlą „pytaj aż do skutku” da się zamknąć, nawet gdy nikt nie wpisze poprawnej liczby.

docs.python.org, The Python Tutorial, rozdz. 8.3 (Handling Exceptions)
Ćwiczenie · przy komputerze · 12 minut

Ćwiczenie: program, który się nie wywala

  1. Załóż plik divide.py. Program pyta o dwie liczby całkowite i wypisuje ich iloraz. Dodaj osobny except dla ValueError i osobny dla ZeroDivisionError. Sprawdź na parach: 10 i 4, 10 i 0, 10 i „dwa”.
  2. Przerób divide.py tak, żeby pytał o dzielnik w pętli while True, aż dostanie liczbę, przez którą da się podzielić. Gdzie musi stać break?
  3. Nowy plik count.py: program otwiera notes.txt, wypisuje liczbę linii, a gdy pliku nie ma, pisze „Nie ma takiego pliku.” zamiast czerwonego komunikatu. Uruchom najpierw bez pliku, potem z plikiem o trzech liniach.
Jak to sprawdzić

Program jest gotowy dopiero wtedy, gdy przy żadnym z podanych wejść nie widzicie słowa Traceback. Jeśli je widzicie, przeczytajcie ostatnią linię komunikatu: nazwa typu przed dwukropkiem to dokładnie to, co brakuje po except.

Sprawdzenie

Trzy pytania na koniec

  1. Czym różni się błąd składni od wyjątku?
  2. Która linia komunikatu o błędzie mówi, co się stało, i czego z niej używamy w except?
  3. Program ma pytać o liczbę, aż użytkownik poda poprawną. Czego potrzeba oprócz try i except?
Podsumowanie

A jak to wygląda w produkcji?

Na lekcjiW produkcjiStatus
try wokół int(input())Formularz płatności: gdy w polu „kwota” nie ma liczby, strona pokazuje komunikat przy polu zamiast się zamknąćcodziennie
except FileNotFoundErrorAplikacja przy starcie czyta plik ustawień; gdy go nie ma, tworzy domyślny i działa dalejstandard
Czerwony komunikatSerwer zapisuje cały ślad błędu do dziennika dla programisty, a użytkownikowi pokazuje jedno zdaniestandard w firmach
except bez nazwy typuNa przeglądzie kodu odrzucane, bo ukrywa również literówki i błędy, o których nikt się nie dowiereguła zespołów