Czym jest obsługa wyjątków?
Obsługa wyjątków to sposób, w jaki program reaguje na błędy pojawiające się w trakcie działania. Kod, który może zawieść, trafia do chronionego bloku, takiego jak try, a gdy zostanie zgłoszony błąd, sterowanie przeskakuje do procedury obsługi, takiej jak except albo catch, zamiast przerwać program.
Aktualizacja: 24 września 2026
Program, który pyta ludzi o wiek, prędzej czy później dostanie "twenty" zamiast 20. Konwersja takiego tekstu to błąd wykonania: int("twenty") zgłasza ValueError, a bez planu na taką sytuację program się zatrzymuje. Obsługa wyjątków to właśnie taki plan. Oznaczasz kod, który może zawieść, i piszesz kod, który wykona się, jeśli tak się stanie.
Next year you will be 35
Not a number: twenty
Next year you will be 20
Done
Zła odpowiedź zostaje zgłoszona, a pętla przechodzi do następnej. Bez try program wyświetliłby jedną linię, a potem traceback.
Jak działa obsługa wyjątków
- Kod wewnątrz
trywykonuje się normalnie. - Jakaś operacja się nie udaje, a środowisko uruchomieniowe zgłasza wyjątek: obiekt z typem (
ValueError) i komunikatem (invalid literal for int() with base 10: 'twenty'). - Blok
tryzatrzymuje się na tej linii. Pozostałe linie są pomijane, dlatego dla "twenty" nie wyświetla się "Next year you will be". - Środowisko porównuje typ wyjątku z każdą klauzulą
except, od góry do dołu, i uruchamia pierwszą pasującą. - Gdy procedura obsługi się skończy, program kontynuuje od pierwszej linii po całej instrukcji
try. - Jeśli żadna klauzula nie pasuje, wyjątek opuszcza bieżącą funkcję, a szukanie trwa dalej w funkcji, która ją wywołała, potem w funkcji wywołującej tamtą. Nazywa się to zwijaniem stosu wywołań. Jeśli szukanie dojdzie do samej góry programu bez dopasowania, program kończy się tracebackiem.
Krok 6 oznacza, że procedura obsługi nie musi być w funkcji, w której wystąpił błąd. Tutaj awaria następuje dwa wywołania głębiej, a procedura obsługi na dole i tak ją łapie:
parsing 4.50
parsing free
Could not add the prices: could not convert string to float: 'free'
float("free") zawiodło wewnątrz parse_price. Ani parse_price, ani total nie miały procedury obsługi, więc obie zostały porzucone, a "3.20" nigdy nie zostało sparsowane. To główna decyzja projektowa, jaką daje obsługa wyjątków: obsłuż błąd tam, gdzie wiesz, co z nim zrobić, a to często jest daleko od miejsca, w którym się pojawił.
try, except, else i finally
Instrukcja try w Pythonie ma jeszcze dwie opcjonalne części. else wykonuje się tylko wtedy, gdy blok try zakończył się bez wyjątku. finally wykonuje się w każdym przypadku: po sukcesie, po obsłużonym wyjątku, a nawet wtedy, gdy funkcja zwraca wartość z wnętrza try.
no error
finally runs either way
2.0
b was zero
finally runs either way
None
finally to miejsce na sprzątanie: zamknięcie pliku, zwolnienie blokady, zamknięcie połączenia z bazą danych. W Pythonie instrukcja with robi takie sprzątanie dla plików automatycznie i to ona jest zwykle wybierana w ich przypadku.
Zgłaszanie własnych wyjątków
Wyjątki nie służą tylko do błędów wykrywanych przez język. Gdy twoja własna funkcja dostanie dane, z którymi nie może pracować, może zgłosić wyjątek, żeby odmówić, a wywołujący zdecyduje, co dalej. Zdefiniowanie małej klasy wyjątku daje błędowi nazwę, która go opisuje.
70
Refused: cannot take 250, balance is 100
Python używa raise. Java, C++ i JavaScript używają do tego samego throw.
Obsługa wyjątków w innych językach
| Język | Słowa kluczowe | Warto wiedzieć |
|---|---|---|
| Python | try, except, else, finally, raise | Każdy wyjątek to obiekt dziedziczący po BaseException |
| Java | try, catch, finally, throw, throws | Wyjątki kontrolowane, takie jak IOException, trzeba złapać albo zadeklarować przez throws |
| C++ | try, catch, throw | Brak finally; destruktory sprzątają podczas zwijania stosu |
| JavaScript | try, catch, finally, throw | Błędy w kodzie async łapie się przez try wokół await |
| C | brak | Funkcje zwracają kod błędu, a wiele z nich ustawia errno |
| Go | brak dla zwykłych błędów | Funkcje zwracają wartość error, którą sprawdza wywołujący |
Ten sam przykład z parsowaniem w Javie wygląda tak:
try {
int age = Integer.parseInt("twenty");
System.out.println(age + 1);
} catch (NumberFormatException e) {
System.out.println("Not a number: " + e.getMessage());
} finally {
System.out.println("done");
}
Java dzieli wyjątki na dwie grupy. Wyjątki kontrolowane (checked), takie jak IOException, opisują problemy poza kontrolą programu, a kompilator odmawia zbudowania kodu, który ich ani nie łapie, ani nie deklaruje. Wyjątki niekontrolowane (unchecked), czyli podklasy RuntimeException takie jak NullPointerException, zwykle oznaczają błąd w kodzie, a kompilator nie zmusza do ich obsługi.
Częste błędy
- Łapanie wszystkiego. Gołe
except:w Pythonie łapie teżKeyboardInterrupt, więc Ctrl+C przestaje działać, aexcept Exception:łapie błędy, których nigdy nie planowano. Łap konkretny typ, który umiesz obsłużyć. - Połykanie błędu.
except ValueError: passukrywa problem. Co najmniej wyświetl albo zapisz w logach, co poszło nie tak. - Za duży blok
try. Otaczaj tylko te linie, które mogą zgłosić łapany wyjątek, żeby niezwiązany błąd nie został obsłużony przez pomyłkę. - Łapanie błędów zamiast ich naprawiania.
IndexErrorz pętli, która wykonuje o jeden krok za dużo, to błąd w kodzie. Obsługiwanie go utrzymuje zły kod przy życiu. - Oczekiwanie, że
catchzatrzyma awarię w C albo C++. Błąd segmentacji to sygnał od systemu operacyjnego, a nie wyjątek, i w Linuksie oraz macOScatch (...)w C++ nigdy go nie zobaczy.
Co dalej
Błędy, na które reaguje obsługa wyjątków, opisuje strona o błędzie wykonania, a awarię, której nie da się złapać, strona o błędzie segmentacji. Pełną składnię znajdziesz w przewodnikach po wyjątkach w Pythonie, try i catch w Javie, wyjątkach w C++ i try i catch w JavaScripcie. Kurs Java i kurs Python ćwiczą je na prawdziwych zadaniach.
Najczęściej zadawane pytania
Jakie jest 5 słów kluczowych obsługi wyjątków w Javie?
try, catch, finally, throw i throws. try oznacza obserwowany kod, catch obsługuje konkretny typ wyjątku, a finally uruchamia kod sprzątający bez względu na to, czy wyjątek wystąpił. throw zgłasza wyjątek, a throws w sygnaturze metody deklaruje, które wyjątki kontrolowane metoda może przekazać wywołującemu.Czym jest obsługa wyjątków w C++?
try, catch i throw. Rzucić można dowolny typ, ale zgodnie z konwencją rzuca się obiekt dziedziczący po std::exception, na przykład std::runtime_error, i łapie go przez referencję: catch (const std::exception& e). C++ nie ma finally; sprzątanie odbywa się w destruktorach, które uruchamiają się automatycznie podczas zwijania stosu.Czym różni się błąd od wyjątku?
Exception obejmuje problemy, które program może rozsądnie obsłużyć, a Error, na przykład OutOfMemoryError albo StackOverflowError, sygnalizuje awarię JVM, której program zwykle nie powinien próbować łapać. W Pythonie ValueError i ZeroDivisionError to wyjątki, mimo że w nazwie mają słowo Error.Czym różni się throw od throws w Javie?
throw to instrukcja, która zgłasza jeden wyjątek w danym miejscu: throw new IllegalArgumentException("negative age");. throws to część deklaracji metody, która wymienia wyjątki kontrolowane, jakie metoda może przekazać wywołującemu: void load() throws IOException. Kompilator wymaga wtedy, żeby każdy wywołujący albo złapał ten wyjątek, albo też go zadeklarował.Czy obsługa wyjątków spowalnia kod?
try jest tanie w większości nowoczesnych języków. Od Pythona 3.11 try nie kosztuje prawie nic, gdy żaden wyjątek nie zostaje zgłoszony, a główne kompilatory C++ nie dodają kosztu w czasie wykonania na ścieżce, na której nic nie jest rzucane. Zgłoszenie i złapanie wyjątku jest dużo wolniejsze niż test if, więc w pętlach krytycznych dla wydajności sprawdzaj typowe przypadki zamiast polegać na wyjątkach.