Sobes.tech
Middle

Como funcionam as exceções aninhadas em Python?

sobes.tech IA

Resposta da IA

As exceções aninhadas, também conhecidas como encadeamento de exceções, permitem manter informações sobre a exceção anterior ao surgir uma nova. Isto é útil para depuração e compreensão das causas do erro.

No Python 3, por padrão, quando uma nova exceção ocorre dentro de um bloco except ou finally, a exceção original é automaticamente vinculada à nova.

Esta ligação é armazenada no atributo __cause__ da nova exceção.

A ligação explícita pode ser feita usando a palavra-chave raise from.

# Exemplo de ligação automática
def divide(a, b):
    try:
        return a / b
    except TypeError:
        # Durante o tratamento de TypeError, pode surgir outra exceção
        # A exceção original (TypeError) será vinculada à nova
        raise ValueError("Tipo de operandos incorreto")

try:
    divide("a", 0)
except ValueError as e:
    # e.__cause__ conterá um TypeError
    print(f"Erro: {e}")
    if e.__cause__:
        print(f"Causado por: {e.__cause__}")

print("-" * 20)

# Exemplo de ligação explícita com raise from
class CustomError(Exception):
    pass

def tricky_function():
    try:
        # Tentativa de divisão por zero, gera ZeroDivisionError
        result = 1 / 0
    except ZeroDivisionError as original_exc:
        # Criar uma nova exceção e vinculá-la à original
        raise CustomError("Erro no cálculo") from original_exc

try:
    tricky_function()
except CustomError as e:
    # e.__cause__ conterá ZeroDivisionError
    print(f"Erro: {e}")
    if e.__cause__:
        print(f"Causado por: {e.__cause__}")

print("-" * 20)

# Supressão de ligação com raise ... from None
try:
    try:
        # Exceção original
        raise ValueError("Erro original")
    except ValueError:
        # Durante o tratamento de ValueError, surge outra exceção,
        # mas a ligação é suprimida
        raise TypeError("Nova erro") from None
except TypeError as e:
    # e.__cause__ será None
    print(f"Erro: {e}")
    if e.__cause__ is None:
        print("Razão não especificada.")

A palavra-chave raise sem argumentos relança a última exceção.

# Exemplo de re-lançamento de exceção
def process_data(data):
    try:
        # Suponha que algo possa falhar aqui
        if not data:
            raise ValueError("Dados ausentes")
        print("Dados processados")
    except ValueError:
        print("Capturou ValueError")
        # Re-lançar a mesma exceção
        raise

try:
    process_data("")
except ValueError as e:
    print(f"Exceção relançada capturada: {e}")

Exceções aninhadas melhoram a legibilidade das rastreabilidades de erros e ajudam a localizar mais rapidamente a causa raiz do problema.