Da trilha de Python Este conceito ainda não saiu como card do dia. ir para o card de hoje

Python Erros Intermediário

Exceções

Em Python, exceções são eventos que interrompem o fluxo normal do programa quando algo dá errado. Em vez de verificar erros a cada linha, você pode capturar exceções com try/except, garantindo que o programa continue ou falhe de forma controlada.

A estrutura try pode ter múltiplos except para tratar tipos específicos de erro, um bloco else executado se nenhuma exceção ocorrer, e um finally que sempre roda, mesmo que haja erro ou return. Isso permite separar a lógica principal do tratamento de falhas e da limpeza de recursos.

As exceções formam uma hierarquia: todas herdam de BaseException, e as mais comuns herdam de Exception. Capturar Exception é genérico demais; prefira tipos específicos. Você também pode criar suas próprias exceções herdando de Exception, e usar raise ... from ... para encadear a causa original, preservando o contexto do erro.

Neste card, vamos praticar desde o tratamento básico até a criação de exceções personalizadas com mensagens claras e encadeamento de causas.

Pontos-chave

  • try/except captura exceções; else roda se não houver erro; finally sempre executa.
  • Capture exceções específicas (ex.: ValueError) em vez de Exception genérica.
  • Crie exceções próprias herdando de Exception para erros do seu domínio.
  • Use raise NovaExcecao(...) from erro_original para preservar a causa raiz.
  • A ordem dos except importa: do mais específico para o mais genérico.
excecoes.py
def dividir(a, b):
    try:
        resultado = a / b
    except ZeroDivisionError as e:
        print(f"Erro: divisão por zero ({e})")
        return None
    except TypeError as e:
        print(f"Erro: tipos inválidos ({e})")
        return None
    else:
        print("Divisão realizada com sucesso.")
        return resultado
    finally:
        print("Fim da operação de divisão.")

print(dividir(10, 2))
print(dividir(10, 0))
print(dividir(10, "a"))

# Exceção personalizada
class SaldoInsuficienteError(Exception):
    """Erro lançado quando o saldo é insuficiente para um saque."""
    pass

def sacar(saldo, valor):
    if valor > saldo:
        raise SaldoInsuficienteError(f"Saldo {saldo} insuficiente para sacar {valor}")
    return saldo - valor

try:
    novo_saldo = sacar(100, 150)
except SaldoInsuficienteError as e:
    print(f"Falha no saque: {e}")
else:
    print(f"Novo saldo: {novo_saldo}")

Exercícios

  1. 1
    Fácil

    Tratando divisão por zero

    Escreva uma função dividir_seguro(a, b) que retorna o resultado da divisão a / b. Se b for zero, capture a exceção ZeroDivisionError e retorne None, imprimindo uma mensagem de erro. Use try/except.

    Resolver
  2. 2
    Médio

    Exceção personalizada com encadeamento

    Crie uma exceção personalizada IdadeInvalidaError que herda de Exception. Escreva uma função validar_idade(idade) que lança IdadeInvalidaError se a idade for negativa ou maior que 150, encadeando a causa com raise ... from ... a partir de um ValueError. Capture a exceção e imprima a mensagem e a causa.

    Resolver
  3. 3
    Desafio

    Sistema de saque com exceções personalizadas e finally

    Implemente uma classe ContaBancaria com atributos titular e saldo. O método sacar(valor) deve lançar SaldoInsuficienteError (personalizada) se o valor for maior que o saldo, e ValueError se o valor for negativo. Use try/except/else/finally para: tentar o saque, capturar SaldoInsuficienteError e ValueError, imprimir mensagens apropriadas, e no finally imprimir "Operação finalizada". O programa deve testar três casos: saque válido, saque com saldo insuficiente e saque com valor negativo.

    Resolver

Continue estudando