🌗 ← Índice

🐍 Python P07 — Tratamento de Erros


Data: 05/07/2026

Nível: Básico → Intermediário




Tu já viu teu código explodir com NameError, TypeError ou FileNotFoundError. Hoje tu vai aprender a dominar o caos — prever falhas, tratá-las com elegância e até criar teus próprios erros.




🎯 O que vamos aprender


  • `try` / `except` — capturando exceções
  • `else` e `finally` — código condicional pós-try
  • `raise` — lançando erros de propósito
  • Criando exceções próprias (classes de erro)
  • Boas práticas: nunca use `except:` pelado



  • 💥 Por que erros acontecem


    Python é uma linguagem dinâmica e interpretada. Erros só aparecem em tempo de execução — não tem compilador pra te salvar.


    
    # Isso roda até chegar na bomba:
    print("Tudo certo")
    x = 1 / 0          # ZeroDivisionError — crash!
    print("Nunca vou rodar")
    

    Solução: envolver código arriscado com try/except.




    🛡️ `try/except` — o básico


    
    try:
        numero = int(input("Digite um número: "))
        print(f"100 / {numero} = {100 / numero}")
    except ValueError:
        print("Isso não é um número, animal.")
    except ZeroDivisionError:
        print("Dividir por zero não rola.")
    

    O Python tenta o bloco try. Se der ValueError, cai no primeiro except. Se der ZeroDivisionError, cai no segundo.


    Capturar múltiplas exceções juntas


    
    except (ValueError, ZeroDivisionError) as e:
        print(f"Deu ruim: {e}")
    

    Capturar o objeto da exceção


    
    except FileNotFoundError as e:
        print(f"Arquivo '{e.filename}' não encontrado.")
    



    🎯 `else` — só roda se NÃO deu erro


    
    try:
        arquivo = open("dados.txt")
    except FileNotFoundError:
        print("Arquivo não existe, criando...")
        arquivo = open("dados.txt", "w")
    else:
        # Só chega aqui se open() funcionou
        conteudo = arquivo.read()
        print(f"Li {len(conteudo)} caracteres")
    

    Regra: else roda se (e somente se) o try não lançou exceção.




    🧹 `finally` — sempre roda (com ou sem erro)


    
    conexao = None
    try:
        conexao = conectar_banco()
        dados = conexao.buscar("clientes")
    except DatabaseError:
        print("Falha na consulta")
    finally:
        if conexao:
            conexao.fechar()   # SEMPRE fecha, mesmo com erro
        print("Recursos liberados")
    

    finally é ideal pra limpar recursos: fechar arquivos, conexões, liberar locks.




    🔥 `raise` — lance você mesmo


    
    def sacar(saldo, valor):
        if valor > saldo:
            raise ValueError(f"Saldo insuficiente: R${saldo} < R${valor}")
        return saldo - valor
    
    try:
        novo_saldo = sacar(100, 200)
    except ValueError as e:
        print(e)  # "Saldo insuficiente: R$100 < R$200"
    



    🏗️ Criando exceções próprias


    
    class SaldoInsuficienteError(Exception):
        """Lançada quando tenta sacar mais do que tem."""
        def __init__(self, saldo, valor):
            self.saldo = saldo
            self.valor = valor
            super().__init__(f"Saldo R${saldo} < saque R${valor}")
    
    def sacar(saldo, valor):
        if valor > saldo:
            raise SaldoInsuficienteError(saldo, valor)
        return saldo - valor
    

    Agora quem chamar sacar() pode capturar especificamente teu erro:


    
    try:
        sacar(100, 200)
    except SaldoInsuficienteError as e:
        print(f"Faltou R${e.valor - e.saldo}")
    



    ⚠️ Nunca faça isso


    
    try:
        fazer_algo_arriscado()
    except:          # ❌ PÉSSIMO — captura TUDO (até Ctrl+C!)
        pass         # ❌ Silencia o erro — impossível debugar
    

    Sempre especifique o tipo de exceção:


    
    try:
        fazer_algo_arriscado()
    except ValueError:   # ✅ Captura só o que interessa
        tratar_erro()
    



    🧩 Exceções comuns que tu vai encontrar


    ExceçãoCausa

    |---|---|

    `ValueError`Tipo certo, valor inválido (ex: `int("abc")`)
    `TypeError`Operação em tipo errado (ex: `"a" + 5`)
    `FileNotFoundError`Arquivo não existe
    `KeyError`Chave inexistente no dicionário
    `IndexError`Índice fora da lista
    `ZeroDivisionError`Divisão por zero
    `ImportError`Módulo não encontrado
    `AttributeError`Objeto não tem o atributo/método



    ✍️ Exercícios


    1. Divisão segura

    Crie uma função dividir(a, b) que retorna a / b, mas se b for zero, retorna None e imprime "Divisão por zero".


    
    # Teu código aqui
    

    2. Leitura de arquivo com fallback

    Escreva um código que tenta abrir config.json. Se não existir, cria ele com {} vazio.


    
    # Teu código aqui
    

    3. Validação de idade

    Crie uma função validar_idade(idade) que:

  • Se idade < 0: lança `ValueError`
  • Se idade > 150: lança `ValueError`
  • Caso contrário: retorna `True`

  • 
    # Teu código aqui
    



    🧪 Desafio


    Crie uma mini-calculadora que:

    1. Pede dois números e uma operação (+, -, *, /)

    2. Trata ValueError se o usuário digitar texto

    3. Trata ZeroDivisionError na divisão

    4. Trata operação inválida com raise próprio

    5. Usa finally pra dar tchau

    6. Pergunta se quer continuar (loop com while)


    
    # Teu código aqui — sem olhar o gabarito!
    



    ✅ Gabarito (tente antes de abrir)


    Exercício 1 — Divisão segura


    
    def dividir(a, b):
        try:
            return a / b
        except ZeroDivisionError:
            print("Divisão por zero")
            return None
    
    print(dividir(10, 2))   # 5.0
    print(dividir(10, 0))   # Divisão por zero \n None
    


    Exercício 2 — Leitura com fallback


    
    import json
    
    try:
        with open("config.json") as f:
            config = json.load(f)
    except FileNotFoundError:
        config = {}
        with open("config.json", "w") as f:
            json.dump(config, f)
        print("config.json criado com {}")
    
    print(config)
    


    Exercício 3 — Validação de idade


    
    def validar_idade(idade):
        if idade < 0:
            raise ValueError("Idade não pode ser negativa")
        if idade > 150:
            raise ValueError("Idade suspeita (>150 anos)")
        return True
    
    # Teste
    try:
        validar_idade(-5)
    except ValueError as e:
        print(e)
    


    Desafio — Mini calculadora


    
    class OperacaoInvalidaError(Exception):
        pass
    
    while True:
        try:
            a = float(input("Número 1: "))
            b = float(input("Número 2: "))
            op = input("Operação (+ - * /): ")
    
            if op == "+":
                resultado = a + b
            elif op == "-":
                resultado = a - b
            elif op == "*":
                resultado = a * b
            elif op == "/":
                resultado = a / b
            else:
                raise OperacaoInvalidaError(f"Operação '{op}' não existe")
    
            print(f"→ {a} {op} {b} = {resultado}")
    
        except ValueError:
            print("Digite um número válido!")
        except ZeroDivisionError:
            print("Não pode dividir por zero!")
        except OperacaoInvalidaError as e:
            print(e)
        finally:
            continuar = input("\nContinuar? (s/n): ").lower()
            if continuar != "s":
                print("Valeu, falou!")
                break
    




    **Próxima aula:** P08 — Módulos e Pacotes (import, venv, pip, `__name__`)