Middle
Jak działają zagnieżdżone wyjątki w Pythonie?
sobes.tech AI
Odpowiedź od AI
Zagnieżdżone wyjątki, znane również jako łańcuchy wyjątków, umożliwiają zachowanie informacji o poprzednim wyjątku podczas wystąpienia nowego. Jest to przydatne podczas debugowania i zrozumienia przyczyn błędu.
W Pythonie 3 domyślnie, gdy w bloku except lub finally występuje nowy wyjątek, oryginalny wyjątek jest automatycznie powiązany z nowym.
To powiązanie jest przechowywane w atrybucie __cause__ nowego wyjątku.
Eksplitywne powiązanie można wykonać za pomocą słowa kluczowego raise from.
# Przykład automatycznego powiązania
def divide(a, b):
try:
return a / b
except TypeError:
# Podczas obsługi TypeError może wystąpić inny wyjątek
# Oryginalny wyjątek (TypeError) zostanie powiązany z nowym
raise ValueError("Nieprawidłowy typ operandów")
try:
divide("a", 0)
except ValueError as e:
# e.__cause__ będzie zawierać TypeError
print(f"Błąd: {e}")
if e.__cause__:
print(f"Przyczyna: {e.__cause__}")
print("-" * 20)
# Przykład jawnego powiązania za pomocą raise from
class CustomError(Exception):
pass
def tricky_function():
try:
# Próba dzielenia przez zero, generuje ZeroDivisionError
result = 1 / 0
except ZeroDivisionError as original_exc:
# Tworzymy nowy wyjątek i łączymy go z oryginalnym
raise CustomError("Błąd podczas obliczeń") from original_exc
try:
tricky_function()
except CustomError as e:
# e.__cause__ będzie zawierać ZeroDivisionError
print(f"Błąd: {e}")
if e.__cause__:
print(f"Przyczyna: {e.__cause__}")
print("-" * 20)
# Wyłączenie powiązania za pomocą raise ... from None
try:
try:
# Oryginalny wyjątek
raise ValueError("Błąd początkowy")
except ValueError:
# Podczas obsługi ValueError występuje inny wyjątek,
# ale powiązanie jest wyłączone
raise TypeError("Nowy błąd") from None
except TypeError as e:
# e.__cause__ będzie None
print(f"Błąd: {e}")
if e.__cause__ is None:
print("Przyczyna nie została podana.")
Słowo kluczowe raise bez argumentów ponownie podnosi ostatni wyjątek.
# Przykład ponownego podniesienia wyjątku
def process_data(data):
try:
# Załóżmy, że coś może pójść nie tak
if not data:
raise ValueError("Brak danych")
print("Dane przetworzone")
except ValueError:
print("Przechwycono ValueError")
# Ponownie podnosi ten sam wyjątek
raise
try:
process_data("")
except ValueError as e:
print(f"Przechwycono ponownie podniesiony wyjątek: {e}")
Zagnieżdżone wyjątki poprawiają czytelność ścieżek błędów i pomagają szybciej zlokalizować przyczynę problemu.