Tratamento de exceções
Esta aula aborda o tratamento de exceções em Python, cobrindo as estruturas try/except/else/finally, os principais tipos de exceção, o comando raise e boas práticas para escrever código robusto e legível.
Nesta aula, vamos aprender como lidar com erros em Python de forma controlada, utilizando o sistema de exceções da linguagem. O tratamento adequado de exceções é essencial para construir programas que não quebrem inesperadamente e que forneçam mensagens úteis ao usuário ou ao desenvolvedor.
Veremos como usar os blocos try, except, else e finally, conheceremos os principais tipos de exceção, aprenderemos a levantar exceções com raise e discutiremos boas práticas para um código mais limpo e seguro.
try/except/else/finally
O bloco try permite testar um trecho de código quanto a erros. Se ocorrer uma exceção, o fluxo é desviado para o bloco except, que trata o erro. Opcionalmente, podemos incluir um bloco else, executado se nenhuma exceção for levantada, e um bloco finally, que sempre executa, independentemente de ocorrer erro ou não.
Exemplo básico:
try:
resultado = 10 / 0
except ZeroDivisionError:
print("Divisão por zero não é permitida.")
else:
print(f"Resultado: {resultado}")
finally:
print("Bloco finally sempre executa.")Neste exemplo, a divisão por zero levanta ZeroDivisionError, o except captura e imprime a mensagem, o else não executa, e o finally executa ao final.
Tipos de exceção
Python possui diversas exceções embutidas, organizadas em uma hierarquia. As mais comuns incluem:
Exception– base para todas as exceções não-sistema.ValueError– quando uma função recebe um argumento com tipo correto mas valor inadequado.TypeError– quando uma operação ou função recebe um argumento de tipo inadequado.IndexError– ao acessar um índice inválido em uma sequência.KeyError– ao acessar uma chave inexistente em um dicionário.FileNotFoundError– ao tentar abrir um arquivo que não existe.
Podemos capturar exceções específicas ou usar uma cláusula except genérica (não recomendado). Exemplo:
try:
numero = int(input("Digite um número: "))
except ValueError:
print("Valor inválido!")
except KeyboardInterrupt:
print("\nOperação cancelada.")raise
O comando raise permite levantar uma exceção intencionalmente. Podemos usar uma exceção embutida ou criar uma personalizada. Exemplo:
def dividir(a, b):
if b == 0:
raise ValueError("Divisor não pode ser zero.")
return a / b
try:
print(dividir(10, 0))
except ValueError as e:
print(e)Também é possível re-lançar uma exceção capturada com raise vazio, preservando a pilha de chamadas.
Boas práticas
Algumas recomendações para tratamento de exceções:
- Seja específico: capture exceções específicas, não use
except Exceptionouexcept:a menos que seja realmente necessário. - Evite silenciar exceções: não use
except: passsem registrar o erro de alguma forma. - Use finally para limpeza: feche arquivos, conexões ou libere recursos no
finally. - Não abuse de exceções para controle de fluxo: prefira estruturas condicionais quando possível.
- Documente exceções: em funções, indique quais exceções podem ser levantadas.
Exercícios
Crie uma função que recebe dois números e retorna a divisão. Trate a exceção de divisão por zero e imprima uma mensagem amigável.
✓ Resposta:def dividir(a, b): try: return a / b except ZeroDivisionError: print("Erro: divisão por zero.") return NoneEscreva um código que tenta converter uma string para inteiro. Se falhar, capture ValueError e exiba uma mensagem. Use else para imprimir o número convertido e finally para imprimir "Fim da conversão".
✓ Resposta:try: valor = int(input("Digite um número: ")) except ValueError: print("Valor inválido!") else: print(f"Número convertido: {valor}") finally: print("Fim da conversão.")Crie uma função que levanta uma exceção personalizada chamada SaldoInsuficienteError (herdando de Exception) quando o saldo for menor que o saque. Em seguida, trate essa exceção.
✓ Resposta:class SaldoInsuficienteError(Exception): pass def sacar(saldo, valor): if valor > saldo: raise SaldoInsuficienteError("Saldo insuficiente para o saque.") return saldo - valor try: novo_saldo = sacar(100, 150) except SaldoInsuficienteError as e: print(e)Escreva um programa que tenta abrir um arquivo chamado "dados.txt" para leitura. Se o arquivo não existir, capture FileNotFoundError e crie o arquivo. Use finally para fechar o arquivo se ele foi aberto.
✓ Resposta:arquivo = None try: arquivo = open("dados.txt", "r") conteudo = arquivo.read() print(conteudo) except FileNotFoundError: print("Arquivo não encontrado. Criando...") with open("dados.txt", "w") as f: f.write("Arquivo criado.") finally: if arquivo: arquivo.close()Implemente uma calculadora que lê dois números e uma operação (+, -, *, /). Trate exceções como ValueError (entrada inválida) e ZeroDivisionError. Use else para exibir o resultado e finally para imprimir "Operação finalizada".
✓ Resposta:try: a = float(input("Primeiro número: ")) b = float(input("Segundo número: ")) 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 ValueError("Operação inválida.") except ValueError as e: print(f"Erro: {e}") except ZeroDivisionError: print("Erro: divisão por zero.") else: print(f"Resultado: {resultado}") finally: print("Operação finalizada.")