Obsługa błędów w Pythonie: spróbuj / z wyjątkiem / else / w końcu w 2026 roku
Obsługa błędów oddziela „kod, który działa na twoim komputerze” od „kodu, który przetrwa produkcję”. Opcja „try / z wyjątkiem” w Pythonie wygląda prosto, ale pełna forma składająca się z czterech słów kluczowych — „spróbuj / z wyjątkiem / inaczej / w końcu” – koduje zaskakującą ilość struktur pomijanych przez większość samouczków.
W tym przewodniku omówiono: co właściwie oznacza każde słowo kluczowe, sześć wzorców, które zobaczysz w każdej bazie kodu zaplecza, kiedy definiować własne wyjątki oraz trzy antywzorce, które pozwalają błędom prześlizgnąć się przez testy.
Dokładnie cztery słowa kluczowe
Klauzula „else” jest rzadko używana. Mówi: „Ten następny bit zależy od powodzenia próby, ale nie chcę, żeby był chroniony przez to samo, z wyjątkiem”. To właściwe miejsce na szczęśliwą kontynuację ścieżki — umieszczenie jej w try przypadkowo powoduje wyłapanie niepowiązanych wyjątków z ship(result).
Sześć wzorów
1. Ponów próbę w przypadku przejściowej awarii
Reguła: ponów próbę TYLKO w przypadku błędów przejściowych (sieć, przekroczenie limitu czasu, 429, 503). Nigdy nie próbuj ponownie w przypadku ValueError, KeyError, TypeError — są to błędy w kodzie i ponowna próba powoduje jedynie trzykrotne uruchomienie błędu.
2. Strzeż się za pomocą „else”.
Opcja „else” gwarantuje, że „plik” został pomyślnie otwarty ORAZ czyszczenie zakresu za pomocą „z”. Uwaga: Funkcja „process()” może wywołać błąd „ValueError” — który będzie propagowany w górę i NIE zostanie przechwycony przez „z wyjątkiem FileNotFoundError”.
3. Porządkowanie za pomocą „wreszcie” (zanim istniało „z”)
We współczesnym kodzie należy użyć with db.connect() jako połączenia: — with to cukier zamiast try / wreszcie w typowym przypadku czyszczenia. Sięgaj po wyraźne „wreszcie” tylko wtedy, gdy zasób nie obsługuje protokołu menedżera kontekstu.
4. Podbij ponownie z dodatkowym kontekstem
raise NewException(...) from e łączy oryginalny wyjątek z nowym, więc śledzenie pokazuje OBU. Nigdy nie pisz „raise NewException(str(e))” — spowoduje to odrzucenie oryginalnego śledzenia.
5. Złap najwęższy wyjątek, jaki możesz
Zasada: im węższy wyjątek, tym lepiej. Jeśli nie wiesz, co może wywołać „proces”, uruchom go i dowiedz się. „z wyjątkiem wyjątku:” to zapach kodu w 90% przypadków.
6. „podbij” wewnątrz „z wyjątkiem” — podbij ponownie czysto
Samo „podbicie” utrzymuje oryginalny ślad w stanie nienaruszonym. Nigdy nie „podnoś e” (Python 3 jest mądry, ale samo „podnoszenie” jest formą idiomatyczną).
Niestandardowe wyjątki — kiedy warto
Zdefiniuj własną klasę wyjątków, gdy:
1. Osoby wywołujące muszą konkretnie z wyjątkiem MyError: (tj. masz wywoływalny interfejs API, a użytkownicy muszą rozgałęziać się w zależności od typu błędu).
2. Twoja biblioteka/usługa zgłasza wiele powiązanych błędów, które mają ten sam kontekst.
Teraz osoby dzwoniące mogą wyłapywać informacje szeroko („z wyjątkiem PaymentError”) lub wąsko („z wyjątkiem CardDeclinedError”). Ustrukturyzowane atrybuty wyjątku (e.card_last4) umożliwiają programom obsługi błędów budowanie przydatnego UX bez analizowania komunikatów o wyjątkach.
Anty-wzorzec: definiowanie niestandardowego wyjątku, który istnieje tylko po to, aby zostać wywołany tylko raz i nigdy nie zostać przechwycony. To po prostu „podnieś ValueError(”...)”. Niestandardowe wyjątki zyskują na wadze dzięki złapaniu.
Trzy anty-wzorce ukrywające błędy
Antywzorzec 1: Goły, z wyjątkiem
Samo except przechwytuje sygnały, które powinny zakończyć działanie programu (Ctrl-C, sys.exit, MemoryError. Nigdy tego nie pisz. Jeśli naprawdę chcesz przechwycić każdy niekrytyczny wyjątek, użyj z wyjątkiem wyjątku: — który WCIĄŻ wychwytuje za dużo, ale przynajmniej przestrzega Ctrl-C.
Antywzorzec 2: Wyciszanie bez logowania
Każdy przechwycony wyjątek powinien zostać obsłużony (z określonym rozwiązaniem awaryjnym) lub zarejestrowany. „pass” w wyjątku to błąd występujący w zwolnionym tempie — kod wydaje się działać, dyskretnie odrzucając dane.
Antywzorzec 3: z wyjątkiem wyjątku: wokół wszystkiego
Problem: jeśli operacja stripe.charge powiodła się, ale send_receipt nie powiodła się, klient został obciążony ORAZ przełknąłeś błąd. „Wyjątek” obejmuje cztery różne tryby awarii i nie można ich rozróżnić.
Poprawka: zawęź zakres try + rozgałęzij z wyjątkiem granicy modułu.
Każda próba obejmuje JEDNĄ operację. Każdy z wyjątkiem wie, co zrobić z TYM konkretnym niepowodzeniem. To jest obsługa błędów na poziomie produkcyjnym.
Dobra obsługa błędów to bardziej projekt niż składnia. „spróbuj / z wyjątkiem / inaczej / w końcu” daje ci narzędzia; dyscypliną jest wybieranie właściwego typu z wyjątkiem typu, najwęższego możliwego zakresu prób i nigdy nie wyciszanie błędów, których nie rozumiesz.
Następny krok: ścieżka Foundations zawiera 10 lekcji na temat obsługi wyjątków, wyjątków niestandardowych i instrukcji „with” — z prawdziwym Pythonem uruchomionym w przeglądarce.