Tratamento de erros é uma parte muito importante ao escrever programas. Ele ajuda seu código a lidar com imprevistos. Imagine que seu programa é como um carro. Se algo der errado, como um pneu furado, ele não pode simplesmente parar. Ele precisa de um plano para lidar com isso.
Em Python, usamos algo chamado try-except
para lidar com erros. Isso permite que seu programa tente fazer algo. Se der errado, ele pega o erro e faz outra coisa. É como ter um plano B para seu código.
Por Que Precisamos Tratar Erros?
Pense na vida real. Você tenta fazer algo. Às vezes, não funciona. Por exemplo, você tenta abrir um arquivo no computador. Mas e se o arquivo não estiver lá? Seu programa pode travar.
Um programa que trava não é bom. Ele pode perder informações. Pode deixar o usuário frustrado. O tratamento de erros evita que isso aconteça. Ele torna seu programa mais forte.
Seu programa se torna mais amigável. Ele pode avisar o usuário sobre o problema. Pode até tentar consertar o que deu errado. Isso é o que chamamos de robustez.
Tipos Comuns de Erros (Exceções)
Em Python, erros são chamados de exceções. Uma exceção é um evento que acontece. Ele interrompe o fluxo normal do seu programa. É como um alerta vermelho.
Existem muitos tipos de exceções. Cada uma significa algo diferente. Por exemplo, uma exceção pode significar que você tentou dividir por zero. Outra pode ser que um arquivo não foi encontrado.
Conhecer os tipos de exceções é útil. Ajuda a entender o que deu errado. E ajuda a criar um plano para cada problema.
Erro de Valor (ValueError
)
Um ValueError
acontece quando o valor que você deu não está certo. Imagine que você pede para alguém digitar a idade. Se a pessoa digita “vinte” em vez de “20”, isso gera um ValueError
. O programa esperava um número, mas recebeu um texto.
idade_texto = "abc"
try:
idade = int(idade_texto) # Tenta transformar "abc" em número
print(f"Sua idade é: {idade}")
except ValueError:
print("Erro: Por favor, digite um número para a idade.")
Neste exemplo, a função int()
tenta converter o texto “abc” em um número. Como “abc” não é um número válido, um ValueError
é gerado. O bloco except ValueError
então entra em ação e imprime a mensagem de erro.
Erro de Tipo (TypeError
)
Um TypeError
ocorre quando você tenta fazer uma operação com tipos de dados que não combinam. Por exemplo, tentar somar um número com um texto. Você não pode adicionar “Olá” a “5”, certo? É a mesma ideia.
num = 10
texto = "cinco"
try:
resultado = num + texto # Tenta somar um número com um texto
print(f"O resultado é: {resultado}")
except TypeError:
print("Erro: Você não pode somar um número com um texto.")
Aqui, o Python não sabe como somar um número inteiro (int
) com um texto (str
). Essa tentativa causa um TypeError
, e o programa informa que a operação não é permitida para esses tipos.
Erro de Nome (NameError
)
Um NameError
aparece quando você tenta usar um nome (de variável, função ou qualquer coisa) que o Python não reconhece. É como tentar chamar alguém por um nome que você nunca ouviu antes – a pessoa simplesmente não existe para você.
try:
print(minha_variavel) # Tenta usar uma variável que não existe
except NameError:
print("Erro: A variável 'minha_variavel' não foi definida.")
Se a variável minha_variavel
não tiver sido criada em nenhum lugar do seu código antes de ser usada, o Python não a encontrará, e um NameError
será lançado.
Erro de Arquivo Não Encontrado (FileNotFoundError
)
O FileNotFoundError
acontece quando seu programa tenta abrir um arquivo, mas ele não está no lugar onde você disse que estaria. É como procurar um livro em uma prateleira, mas ele simplesmente não está lá.
try:
with open("arquivo_inexistente.txt", "r") as f:
conteudo = f.read()
print(conteudo)
except FileNotFoundError:
print("Erro: O arquivo não foi encontrado. Verifique o nome.")
Neste caso, ao tentar abrir arquivo_inexistente.txt
para leitura ("r"
), se o Python não conseguir localizá-lo, ele levantará um FileNotFoundError
, e você receberá a mensagem de que o arquivo não foi encontrado.
Erro de Divisão por Zero (ZeroDivisionError
)
Um ZeroDivisionError
é bem direto: ocorre quando você tenta dividir um número por zero. Na matemática, a divisão por zero é impossível, e o Python segue essa regra, não permitindo tal operação.
try:
resultado = 10 / 0 # Tenta dividir por zero
print(f"O resultado é: {resultado}")
except ZeroDivisionError:
print("Erro: Não é possível dividir por zero!")
Qualquer expressão que resulte em uma divisão por zero, como 10 / 0
, fará com que o Python gere um ZeroDivisionError
. O bloco except
captura essa situação e informa que a operação não pode ser realizada.
Esses são apenas alguns dos erros mais comuns que você pode encontrar ao programar em Python. Existem muitos outros tipos de exceções, cada uma indicando uma situação diferente que pode sair do esperado.
O Poder do try-except
O try-except
é a ferramenta principal. Ele permite que você “tente” um pedaço de código. Se um erro acontecer ali, ele “pega” esse erro. E aí faz o que você mandou.
Como Funciona o try
Dentro do bloco try
, você coloca o código que pode dar problema. É o seu “código arriscado”.
try:
# Código que pode gerar um erro
numero = int(input("Digite um número: "))
resultado = 10 / numero
print(f"O resultado é: {resultado}")
Neste exemplo, pedir um número ao usuário pode gerar um ValueError
. Dividir por esse número pode gerar um ZeroDivisionError
.
Como Funciona o except
O bloco except
vem depois do try
. Ele é executado se um erro ocorrer no try
. Você pode especificar qual erro ele deve pegar.
try:
numero = int(input("Digite um número: "))
resultado = 10 / numero
print(f"O resultado é: {resultado}")
except ValueError:
print("Isso não é um número válido. Por favor, tente novamente.")
except ZeroDivisionError:
print("Não é possível dividir por zero. Tente outro número.")
Aqui, se o usuário digitar texto, o primeiro except
pega. Se digitar zero, o segundo except
pega.
except
Genérico e Múltiplos except
Você pode ter vários except
para diferentes erros. Ou pode ter um except
que pega qualquer erro.
Pegando Erros Específicos
É bom pegar erros específicos. Isso permite que você trate cada erro de forma diferente.
try:
nome_arquivo = input("Digite o nome do arquivo: ")
with open(nome_arquivo, "r") as f:
conteudo = f.read()
print(f"Conteúdo do arquivo:\n{conteudo}")
except FileNotFoundError:
print(f"O arquivo '{nome_arquivo}' não foi encontrado.")
except PermissionError:
print(f"Você não tem permissão para ler o arquivo '{nome_arquivo}'.")
except Exception as e: # Pega qualquer outro erro
print(f"Ocorreu um erro inesperado: {e}")
Aqui, tratamos FileNotFoundError
e PermissionError
. O último except Exception as e
pega qualquer outro erro. E ele mostra a mensagem do erro (e
).
O except
Genérico (Exception
)
Usar except Exception as e
é como pegar todos os peixes na rede. Ele captura qualquer tipo de exceção.
try:
# Algum código que pode dar erro
lista = [1, 2, 3]
print(lista[5]) # Isso vai dar um IndexError
except Exception as e:
print(f"Aconteceu um erro: {e}")
É bom para erros que você não previu. Mas tente usar except
específicos quando puder. Assim, você sabe melhor o que aconteceu.
O else
no try-except
O bloco else
em um try-except
é como uma recompensa. Ele é executado apenas se o código no try
rodar sem nenhum erro.
É útil para colocar coisas que só devem acontecer se tudo deu certo.
try:
num1 = int(input("Digite o primeiro número: "))
num2 = int(input("Digite o segundo número: "))
resultado = num1 / num2
except ValueError:
print("Erro: Por favor, digite apenas números inteiros.")
except ZeroDivisionError:
print("Erro: Não é possível dividir por zero.")
else:
print(f"A divisão de {num1} por {num2} é: {resultado}")
print("Operação realizada com sucesso!")
Neste exemplo, a mensagem “Operação realizada com sucesso!” só aparece se não houver erro.
O finally
no try-except
O bloco finally
é diferente. Ele sempre será executado. Não importa se houve um erro ou não.
É perfeito para “limpar” as coisas. Por exemplo, fechar um arquivo. Ou liberar um recurso do sistema.
arquivo = None
try:
arquivo = open("meu_log.txt", "w") # Tenta abrir um arquivo para escrita
arquivo.write("Isso é um teste.")
except IOError:
print("Erro ao escrever no arquivo.")
finally:
if arquivo: # Verifica se o arquivo foi aberto
arquivo.close()
print("Arquivo fechado com sucesso.")
Mesmo que ocorra um IOError
(erro de entrada/saída), o arquivo será fechado. Isso evita que o arquivo fique “aberto” e cause problemas depois.
Combinando try-except-else-finally
Você pode usar todos eles juntos. Isso cria um tratamento de erro completo.
def processar_dados():
arquivo_aberto = None
try:
caminho_arquivo = input("Digite o caminho do arquivo de dados: ")
arquivo_aberto = open(caminho_arquivo, "r")
primeira_linha = arquivo_aberto.readline()
numero = int(primeira_linha.strip())
resultado = 100 / numero
except FileNotFoundError:
print(f"Erro: O arquivo '{caminho_arquivo}' não foi encontrado.")
except ValueError:
print("Erro: A primeira linha do arquivo não contém um número válido.")
except ZeroDivisionError:
print("Erro: O número no arquivo é zero. Não é possível dividir por zero.")
except Exception as e:
print(f"Ocorreu um erro inesperado: {e}")
else:
print(f"Processamento concluído com sucesso. Resultado: {resultado}")
finally:
if arquivo_aberto:
arquivo_aberto.close()
print("Recursos liberados (arquivo fechado).")
processar_dados()
Este é um exemplo mais complexo. Ele mostra como cada parte se encaixa.
Criando Seus Próprios Erros (Exceções)
Às vezes, você quer que seu próprio código gere um erro. Isso é útil para quando algo importante não acontece.
Você usa a palavra raise
para fazer isso.
Usando raise
Imagine que você está criando uma função para calcular a idade. Se a idade for negativa, isso é um erro. Você pode “levantar” um erro.
def calcular_idade(ano_nascimento):
if ano_nascimento <= 0:
raise ValueError("O ano de nascimento não pode ser zero ou negativo.")
idade = 2025 - ano_nascimento
return idade
try:
minha_idade = calcular_idade(1990)
print(f"Você tem {minha_idade} anos.")
outra_idade = calcular_idade(-5) # Isso vai gerar um erro
print(f"Outra pessoa tem {outra_idade} anos.")
except ValueError as e:
print(f"Erro ao calcular idade: {e}")
Quando calcular_idade(-5)
é chamado, ele gera um ValueError
. Este erro é então capturado pelo except
.
Boas Práticas no Tratamento de Erros
Tratar erros é uma arte. Aqui estão algumas dicas para fazer isso bem.
Seja Específico com os except
Não use except Exception
para tudo. Tente identificar os erros mais prováveis. Trate-os especificamente. Isso torna seu código mais claro. E mais fácil de consertar.
Não “Esconda” os Erros
Não use um except
vazio.
# Não faça isso!
try:
# Código...
except:
pass # Isso "esconde" o erro, você nunca saberá o que aconteceu
Isso faz com que o programa não avise sobre o erro. Você nunca saberá o que deu errado.
Forneça Mensagens Claras
Quando um erro acontecer, avise o usuário. Dê uma mensagem que ele possa entender. Diga o que deu errado. E se possível, como consertar.
Por exemplo, em vez de “Erro!”, use “Erro: O arquivo que você tentou abrir não existe.”
Registre os Erros (logging
)
Para programas maiores, é bom guardar um registro dos erros. Isso se chama logging
. Ele escreve os erros em um arquivo. Assim, você pode olhar depois.
import logging
logging.basicConfig(filename='erros_do_programa.log', level=logging.ERROR,
format='%(asctime)s - %(levelname)s - %(message)s')
try:
resultado = 10 / 0
except ZeroDivisionError as e:
logging.error(f"Erro de divisão por zero: {e}")
print("Ocorreu um erro. Consulte o arquivo de log para mais detalhes.")
O logging
é uma ferramenta poderosa. Ele ajuda a depurar seu programa.
Evite Lógica de Negócio em Blocos except
O bloco except
deve lidar com o erro. Não deve conter a lógica principal do seu programa. Mantenha a separação de tarefas.
Use with open()
para Arquivos
Quando lidar com arquivos, use with open(...)
. Isso garante que o arquivo seja fechado. Mesmo que ocorra um erro.
try:
with open("meu_arquivo.txt", "r") as f:
conteudo = f.read()
print(conteudo)
except FileNotFoundError:
print("Arquivo não encontrado.")
O with
é como um finally
automático para arquivos.
Cenários do Mundo Real
Vamos ver como o tratamento de erros se aplica em situações reais.
Lendo Dados de Usuários
Imagine um site. O usuário digita informações. Você precisa ter certeza que elas são válidas.
- Idade: O usuário digita “vinte”. Seu programa espera um número.
- CEP: O usuário digita um CEP incompleto.
Você usaria try-except
para validar isso. Se a entrada for inválida, você pede de novo. Ou avisa o usuário.
def pedir_idade():
while True:
try:
idade = int(input("Por favor, digite sua idade: "))
if idade <= 0:
raise ValueError("A idade não pode ser zero ou negativa.")
return idade
except ValueError as e:
print(f"Entrada inválida: {e}. Tente novamente.")
minha_idade = pedir_idade()
print(f"Sua idade é: {minha_idade}")
Este loop continua até que o usuário digite uma idade válida.
Conectando a um Banco de Dados
Programas frequentemente se conectam a bancos de dados. A conexão pode falhar.
- O servidor do banco de dados pode estar desligado.
- A senha pode estar errada.
- A internet pode cair.
Você usaria try-except
para tentar a conexão. Se falhar, você avisa. E pode até tentar novamente.
# Exemplo simplificado de conexão com banco de dados
def conectar_banco(usuario, senha):
try:
# Simula uma conexão com banco de dados
if usuario == "admin" and senha == "senha123":
print("Conectado ao banco de dados com sucesso!")
return True
else:
raise ValueError("Usuário ou senha incorretos.")
except ValueError as e:
print(f"Erro de conexão: {e}")
return False
except Exception as e:
print(f"Um erro inesperado ocorreu ao conectar: {e}")
return False
# Testando a função
conectar_banco("admin", "senha123")
conectar_banco("usuario_errado", "senha_errada")
Este código simula uma tentativa de conexão. Ele lida com credenciais erradas. E com outros erros.
Operações com Arquivos
Já falamos sobre isso. Abrir, ler ou escrever em arquivos pode dar muitos erros.
- O arquivo não existe.
- Você não tem permissão para acessá-lo.
- O disco está cheio.
try-except
é essencial aqui.
def ler_arquivo(nome_arquivo):
try:
with open(nome_arquivo, "r") as f:
conteudo = f.read()
print("Conteúdo do arquivo:")
print(conteudo)
except FileNotFoundError:
print(f"Erro: O arquivo '{nome_arquivo}' não foi encontrado.")
except IOError as e:
print(f"Erro de leitura/escrita no arquivo: {e}")
except Exception as e:
print(f"Ocorreu um erro inesperado ao ler o arquivo: {e}")
ler_arquivo("meu_arquivo.txt") # Tenta ler um arquivo existente
ler_arquivo("arquivo_nao_existe.txt") # Tenta ler um arquivo que não existe
Esta função tenta ler um arquivo. Se der erro, ela informa.
Depurando Erros em Python
Quando um erro acontece, Python mostra uma traceback
. É como um mapa do erro. Ele mostra onde o erro aconteceu. E o caminho que o código seguiu até lá.
# Exemplo de traceback
def minha_funcao_interna(divisor):
resultado = 10 / divisor
return resultado
def minha_funcao_principal():
valor = int(input("Digite um número: "))
saida = minha_funcao_interna(valor)
print(f"Resultado final: {saida}")
# Se o usuário digitar 0, ocorrerá um erro e uma traceback
# minha_funcao_principal()
Se você rodar minha_funcao_principal()
e digitar 0
, verá uma traceback
. Ela mostrará que o erro (ZeroDivisionError
) aconteceu em minha_funcao_interna
.
A traceback
é sua amiga. Leia-a com atenção. Ela vai te dizer muito sobre o problema.
Ferramentas de Depuração
Além da traceback
, existem ferramentas. O debugger é uma delas. Ele permite que você pause o programa. Você pode ver o valor das variáveis. Isso ajuda a encontrar o problema.
Para Python, o pdb
(Python Debugger) é uma opção embutida. Ambientes de desenvolvimento (IDEs) como PyCharm ou VS Code têm seus próprios debuggers.
Conclusão
O tratamento de erros é fundamental. Ele torna seus programas mais confiáveis. Mais robustos. E mais fáceis de usar.
Com try-except
, você tem o poder de prever problemas. Você pode criar um plano para cada situação.
Lembre-se de ser específico. Forneça mensagens claras. E use finally
para limpeza.
Dominar o tratamento de erros é um passo grande. Ele te torna um programador melhor. Seus programas serão mais profissionais. E os usuários ficarão mais felizes.
Continue praticando. Teste diferentes cenários. E você se tornará um mestre em lidar com imprevistos no código.