Odcinek 7/15 – Obsługa wyjątków i debugowanie w Pythonie

foto kurs pythona odcinek 7

Cel: po tym rozdziale będziesz wiedzieć:

  • czym różnią się błędy składniowe i wyjątki,
  • jak łapać i obsługiwać błędy w czasie działania programu,
  • jak szukać przyczyn problemów (debugować),
  • jak rzucać własne wyjątki.

1) Błędy vs. wyjątki – co i po co?

Błąd składniowy (SyntaxError) – komputer nawet nie wystartuje programu.
Przykład:

if True print("ups")   # brak dwukropka => SyntaxError

Wyjątek – program ruszył, ale zatrzymał się w trakcie:

x = int("abc")  # ValueError – nie da się zamienić "abc" na liczbę
y = 5 / 0       # ZeroDivisionError – dzielenie przez 0

Python zna dziesiątki wyjątków: ValueError, IndexError, KeyError, FileNotFoundError, TypeError i wiele innych.


2) try i except – przejmowanie kontroli

Podstawowy schemat:

try:
    x = int(input("Podaj liczbę: "))
    print("Wynik:", 10 / x)
except ValueError:
    print("To nie była liczba!")
except ZeroDivisionError:
    print("Nie dziel przez zero!")

Dzięki try/except program się nie wykrzacza, tylko ładnie reaguje.


3) Kilka wyjątków naraz i aliasy

Łapanie różnych błędów w jednej linii:

try:
    data = [1, 2, 3]
    print(data[5])   # za daleko!
except (IndexError, ValueError) as e:
    print("Błąd:", e)

as e – przechowuje komunikat błędu w zmiennej e.


4) else i finally – dodatkowe klauzule

  • else – wykona się, jeśli nie było błędu.
  • finally – wykona się zawsze, np. do zamykania pliku.
try:
    f = open("dane.txt")
    text = f.read()
except FileNotFoundError:
    print("Brak pliku!")
else:
    print("Plik odczytany poprawnie.")
finally:
    print("Zamykam zasoby.")
    if 'f' in locals():
        f.close()

5) Rzucanie własnych wyjątków – raise

Możesz sam powiedzieć: „jeśli coś jest nie tak, przerwij i zgłoś błąd”.

def dziel(a, b):
    if b == 0:
        raise ValueError("Dzielenie przez zero jest zabronione!")
    return a / b

print(dziel(10, 2))  # 5.0
print(dziel(10, 0))  # ValueError

6) Najczęstsze wpadki początkujących

Goły except

try:
    ...
except:
    print("coś poszło nie tak")

Łapie absolutnie wszystko – nawet poważne błędy systemowe.
✔ Lepiej:

except Exception as e:
    print("Błąd:", e)

Brak komunikatu – zawsze pokaż, co poszło źle.

Zbyt szeroka obsługa – łapanie wszystkich wyjątków może ukryć prawdziwy problem.


7) Podstawy debugowania – czyli tropienie błędów

  1. Czytaj traceback – komunikat błędu dokładnie mówi, gdzie i w której linii padło.
  2. Print debugging – wstaw print() z wartościami zmiennych w newralgicznych miejscach.
  3. Debugger w edytorze – np. VS Code: ustaw punkt przerwania (breakpoint), krok po kroku obserwuj zmienne.
  4. Moduł pdb (dla chętnych):
import pdb; pdb.set_trace()

Przydatne przy większych programach.


8) Praktyczne przykłady

Walidacja danych wejściowych

while True:
    try:
        n = int(input("Podaj liczbę całkowitą: "))
        print("Kwadrat:", n * n)
        break
    except ValueError:
        print("To nie liczba, spróbuj jeszcze raz.")

Obsługa plików

try:
    with open("plik.txt") as f:
        for line in f:
            print(line.strip())
except FileNotFoundError:
    print("Plik nie istnieje!")

9) Mini-projekty (praktyka)

A) Kalkulator z obsługą błędów

try:
    a = float(input("a = "))
    b = float(input("b = "))
    op = input("Operacja (+,-,*,/): ")

    if op == "+":
        print(a + b)
    elif op == "-":
        print(a - b)
    elif op == "*":
        print(a * b)
    elif op == "/":
        print(a / b)
    else:
        print("Nieznana operacja")
except ValueError:
    print("Błąd: musisz podać liczby!")
except ZeroDivisionError:
    print("Błąd: dzielenie przez zero!")

B) Parser JSON

import json

txt = '{"name":"Ala","age":20}'
try:
    data = json.loads(txt)
    print("Imię:", data["name"])
except (json.JSONDecodeError, KeyError) as e:
    print("Błąd w danych:", e)

10) Zadania do samodzielnego zrobienia

  1. Tworzenie pliku
    Otwórz plik. Jeśli go nie ma – stwórz go z napisem „start”.
  2. Bezpieczne dzielenie
    Funkcja safe_div(a, b), która zwraca wynik lub komunikat o błędzie.
  3. Lista liczb od użytkownika
    Pobierz liczby oddzielone spacją. Jeśli któraś nie jest liczbą – poproś o poprawkę.
  4. Własny wyjątek
    Utwórz NegativeNumberError i użyj go, by blokować liczby ujemne w funkcji obliczającej pierwiastek.
  5. Logowanie do pliku
    Zastosuj try/except/else/finally, aby zapisać do pliku informację o każdym uruchomieniu programu.

Co zabierasz z odcinka 7?

  • Wiesz, czym różnią się błędy składniowe i wyjątki.
  • Potrafisz stosować try/except, else, finally.
  • Znasz najczęstsze wyjątki (ValueError, IndexError, ZeroDivisionError itd.).
  • Umiesz rzucać własne wyjątki (raise).
  • Poznałeś metody debugowania – od prostych print() po wbudowany debugger.