Programy w języku Python kończą się niepowodzeniem w czasie wykonywania, gdy operacje takie jak dostęp do pliku, analizowanie danych wejściowych lub wywołania sieciowe powodują wyjątki. Obchodzenie się z nimitry/exceptzapewnia responsywność aplikacji, zachowuje użyteczny kontekst i gwarantuje uporządkowanie.
Zanim zaczniesz — podstawowe zasady
- Przechwytuj najbardziej specyficzne typy wyjątków, jakich oczekujesz (na przykład
ValueError,FileNotFoundError), a nie ogólne pojęcie. - Używać
elsena ścieżkę sukcesu ifinallydla kodu, który musi działać bez względu na wszystko. - Preferuj menedżerów kontekstu (
with) dla plików i innych zasobów, aby uprościć czyszczenie. - Pozwól, aby nieoczekiwane błędy się rozprzestrzeniały; zaloguj je i podbij ponownie, zamiast po cichu je połykać.
- Rezerwowe programy obsługi catch-all (
except ExceptionLubexcept BaseException) dla granic najwyższego poziomu, gdzie możesz szybko ponieść porażkę lub jasno zgłosić porażkę.
Metoda 1 — Wyłap określone wyjątki (zalecane)
Krok 1:Zidentyfikuj jedną ryzykowną operację, którą należy chronić.
raw = input("Select a fruit number (0-2): ")Krok 2:Zakończ operacjętry/excepti obsługiwać jawne typy wyjątków.
try:
selection = ["apple", "pear", "banana"][int(raw)]
print("You chose:", selection)
except ValueError:
print("Not a number.")
except IndexError:
print("Choice out of range.")Krok 3:Grupuj powiązane wyjątki, gdy odzyskiwanie jest identyczne.
try:
selection = ["apple", "pear", "banana"][int(raw)]
except (ValueError, IndexError) as e:
print("Invalid selection:", type(e).__name__)Typowe szczególne wyjątki obejmująOSErrorrodzina (pliki),ValueErrorITypeError(dane),ZeroDivisionError(matematyka) iKeyError/IndexError(zbiory).
Metoda 2 — Użyj else i last, aby oddzielić sukces od czyszczenia
Krok 1:Dodaćelsedla kodu, który powinien działać tylko wtedy, gdy nic nie zawiedzie.
try:
f = open("config.json", "r", encoding="utf-8")
except FileNotFoundError:
print("No config file found.")
else:
data = f.read()
print("Loaded", len(data), "bytes.")
f.close()Krok 2:Dodaćfinallydo czyszczenia, które musi nastąpić niezależnie od tego, czy próba się powiodła, czy nie.
f = None
try:
f = open("config.json", "r", encoding="utf-8")
data = f.read()
except OSError as err:
print("OS error:", err)
finally:
if f:
f.close()Metoda 3 — Strzeż swojego punktu wejścia, aby szybko zakończyć się niepowodzeniem i zalogować się
Krok 1:Przenieś swój przepływ pracy domain()funkcjonować.
def main():
# core workflow
# ...
return 0Krok 2:Zakończ połączenie na najwyższym poziomietry/exceptaby zarejestrować nieoczekiwane błędy i zatrzymać program.
POWIĄZANY:Jak utworzyć venv w Pythonie
import logging, sys
logging.basicConfig(level=logging.INFO)
if __name__ == "__main__":
try:
code = main()
except Exception:
logging.exception("Unhandled error")
sys.exit(1)
sys.exit(code)Krok 3:Zwraca niezerowy kod zakończenia w przypadku niepowodzenia sygnalizowania narzędziom automatyzacji, że przebieg nie powiódł się.
# in main(), return 1 or raise an exception when a critical step failsMetoda 4 — Zarządzaj zasobami za pomocąwith(w końcu preferowane zamiast ręcznego)
Krok 1:Zastąp ręczne otwieranie/zamykanie menedżerem kontekstu, aby wymusić terminowe wydanie.
from pathlib import Path
try:
with Path("data.txt").open("r", encoding="utf-8") as f:
print(f.readline().strip())
except FileNotFoundError:
print("Create data.txt first.")Krok 2:Trzymaj tylko ryzykowne operacje w chronionym bloku, aby uniknąć przechwytywania niepowiązanych błędów.
try:
with open("image.png", "rb") as fh:
blob = fh.read()
except OSError as e:
print("File access failed:", e)
# decode/process blob in a separate blockMetoda 5 — Podnoszenie, ponowne podnoszenie i łączenie wyjątków w celu wyczyszczenia ścieżek błędów
Krok 1:Zgłoś konkretny wyjątek, gdy warunek wstępny nie powiedzie się.
def parse_age(s: str) -> int:
if not s.isdigit():
raise ValueError("age must contain only digits")
age = int(s)
if age < 0:
raise ValueError("age cannot be negative")
return ageKrok 2:Zgłaszaj ponownie nieoczekiwane błędy po zalogowaniu, aby osoby dzwoniące również mogły je obsłużyć.
import logging
try:
do_risky_thing()
except OSError as err:
logging.error("OS error: %s", err)
raiseKrok 3:Wyjątki łańcuchowe zraise ... from eaby zachować pierwotną przyczynę podczas dodawania kontekstu.
from pathlib import Path
import json
def load_json(path: str):
try:
text = Path(path).read_text(encoding="utf-8")
except OSError as e:
raise RuntimeError(f"Failed to read {path}") from e
return json.loads(text)Metoda 6 — Obsługa typu „catch-all” na granicach (stosuj oszczędnie)
Krok 1:Używaćexcept Exception as eaby przechwycić wszelkie błędy inne niż wychodzące z systemu, zapisać szczegóły i zdecydować, czy zatrzymać, czy ponowić próbę.
import traceback
try:
risky()
except Exception as e:
print(f"Unexpected {type(e).__name__}: {e}")
traceback.print_exc() # full stack trace
# decide: raise, return error, or abortKrok 2:Tylko złapBaseExceptionjeśli celowo przechwyciszKeyboardInterruptLubSystemExit, a następnie natychmiast ponownie podbij.
try:
service_loop()
except BaseException as e:
print(f"Caught {type(e).__name__}; shutting down cleanly.")
raise # never swallow interrupts or SystemExitMetoda 7 — Obsługuj wiele błędów za pomocą grupy wyjątków i wyjątku* (Python 3.11+)
Krok 1:PodnieśExceptionGrouppodczas agregowania błędów z pracy równoległej lub wsadowej.
def run_tests(tests):
errors = []
for t in tests:
try:
t.run()
except Exception as e:
e.add_note(f"Test {t.name} failed")
errors.append(e)
if errors:
raise ExceptionGroup("Batch failures", errors)Krok 2:Używaćexcept*do obsługi tylko pasujących typów wyjątków w grupie.
try:
run_tests(tests)
except* (ValueError, TypeError):
print("Some data errors occurred.")
except* OSError:
print("Some OS errors occurred.")Szybkie wzorce rozwiązywania problemów
- Analiza danych wejściowych: zawiń
int()Lubfloat()zexcept ValueErrori ponownie poproś użytkownika. - Plik we/wy: catch
FileNotFoundError,PermissionErrorlub ogólnyOSErrori przejdź na ścieżkę zastępczą. - Wywołania sieciowe/API: przechwytuj przekroczenia limitu czasu/błędy połączenia specyficzne dla biblioteki i implementuj ograniczoną ponowną próbę z wycofywaniem.
- Zawsze rejestruj typ i komunikat wyjątku; dla pełnych śladów użyj
logging.exception()Lubtraceback.print_exc().
Kilka skupionych wzorców, takich jak konkretneexceptklauzule,else/finally, a strażnicy najwyższego poziomu sprawią, że Twoje programy w języku Python będą bardziej odporne, bez ukrywania prawdziwych błędów.















