Sobes.tech
Middle

Ako fungujú vnorené výnimky v Pythone?

sobes.tech AI

Odpoveď od AI

Vložené výnimky, známe aj ako reťazenie výnimiek, umožňujú zachovať informácie o predchádzajúcej výnimke pri vzniku novej. To je užitočné na ladenie a pochopenie príčin chyby.

V Pythone 3 sa štandardne pri vzniku novej výnimky v bloku except alebo finally automaticky spojí pôvodná výnimka s novou.

Táto väzba sa uchováva v atribúte __cause__ novej výnimky.

Explicitné spojenie je možné vykonať pomocou kľúčového slova raise from.

# Príklad automatického spojenia
def divide(a, b):
    try:
        return a / b
    except TypeError:
        # Počas spracovania TypeError môže vzniknúť iná výnimka
        # Pôvodná výnimka (TypeError) bude spojená s novou
        raise ValueError("Zlý typ operandu")

try:
    divide("a", 0)
except ValueError as e:
    # e.__cause__ bude obsahovať TypeError
    print(f"Vyskytla sa chyba: {e}")
    if e.__cause__:
        print(f"Vyvolané z: {e.__cause__}")

print("-" * 20)

# Príklad explicitného spojenia pomocou raise from
class CustomError(Exception):
    pass

def tricky_function():
    try:
        # Pokus o delenie nulou, spôsobí ZeroDivisionError
        result = 1 / 0
    except ZeroDivisionError as original_exc:
        # Vytvoríme nové výnimku a spojíme ju s pôvodnou
        raise CustomError("Chyba pri výpočte") from original_exc

try:
    tricky_function()
except CustomError as e:
    # e.__cause__ bude obsahovať ZeroDivisionError
    print(f"Vyskytla sa chyba: {e}")
    if e.__cause__:
        print(f"Vyvolané z: {e.__cause__}")

print("-" * 20)

# Skrytie spojenia pomocou raise ... from None
try:
    try:
        # Pôvodná výnimka
        raise ValueError("Pôvodná chyba")
    except ValueError:
        # Počas spracovania ValueError vznikne iná výnimka,
        # ale väzba je skrytá
        raise TypeError("Nová chyba") from None
except TypeError as e:
    # e.__cause__ tu bude None
    print(f"Vyskytla sa chyba: {e}")
    if e.__cause__ is None:
        print("Príčina nie je uvedená.")

Kľúčové slovo raise bez argumentov opäť vyvolá posledný výnimku.

# Príklad opätovného vyvolania výnimky
def process_data(data):
    try:
        # Predpokladajme, že tu môže dôjsť k chybe
        if not data:
            raise ValueError("Chýbajúce údaje")
        print("Údaje spracované")
    except ValueError:
        print("Zachytili sme ValueError")
        # Opätovne vyvoláme tú istú výnimku
        raise

try:
    process_data("")
except ValueError as e:
    print(f"Zachytili sme opätovne vyvolanú výnimku: {e}")

Vnorené výnimky zlepšujú čitateľnosť trasovania chýb a pomáhajú rýchlejšie lokalizovať pôvodný problém.