Erros de sintaxe, como um loop for incomlpeto, devem ser corrigidos antes de rodar o código:
>>> for i in range(5):
... pass
...
SyntaxError: expected an indented block
Erros lógicos incluem tentativas de operações inválidas, como concatenar um número com uma string, converter valores não numéricos para inteiro, ou acessar índices inexistentes em coleções.
# Tentativa de soma inválida
result = 10 + "texto"
# Conversão de string não numérica
valor = "abc"
num = int(valor)
# Acesso a índice fora dos limites
lista = ["maçã", "banana"]
item = lista[5]
# Chave inexistente em dicionário
dicionário = {"nome": "Ana"}
valor_chave = dicionário["idade"]
# Atributo inexistente em classe
class MinhaClasse:
pass
MinhaClasse.x
# Divisão por zero
quotient = 1 / 0
Para aumentar a robustez e a tolerância a falhas do programa, é essencial implementar tratamento de exceções. A estrutura básica envolve os blocos try e except:
try:
bloco de código a ser monitorado
except TipoDeExceção:
lógica de tratamento quando a exceção ocorre
Por exemplo:
try:
print("Início da execução")
print(variavel_inexistente) # Isso levanta NameError
print("Fim da execução")
except NameError as error:
print("Exceção capturada: %s" % error)
print("Continuação do programa")
# Saída:
# Início da execução
# Exceção capturada: name 'variavel_inexistente' is not defined
# Continuação do programa
Quando o código monitorado pode gerar diferentes tipos de exceções, você pode usar múltiplos blocos except para tratar cada caso separadamente, similar a uma estrutura elif:
try:
bloco de código a ser monitorado
except NomeExceção1:
tratamento para NomeExceção1
except IndiceExceção:
tratamento para IndiceExceção
except ChaveExceção:
tratamento para ChaveExceção
Exemplo com uma função de conversão:
def converter_para_inteiro(objeto):
try:
resultado = int(objeto)
except ValueError as e:
print("Erro de valor: %s" % e)
resultado = None
except TypeError as e:
print("Erro de tipo: %s" % e)
resultado = None
return resultado
converter_para_inteiro("xyz") # Erro de valor: invalid literal for int() with base 10: 'xyz'
converter_para_inteiro({"a": 1}) # Erro de tipo: int() argument must be a string, a bytes-like object or a number, not 'dict'
Para tratar múltiplos tipos de exceções com a mesma lógica, agrupe-as em uma tupla:
try:
bloco de código a ser monitorado
except (NomeExceção, IndiceExceção, TipoExceção):
tratamento unificado para essas exceções
Para capturar qualquer exceção desconhecida, utilize a classe base Exception:
try:
bloco de código a ser monitorado
except NomeExceção:
tratamento específico
except Exception:
tratamento genérico para outras exceções
O bloco else pode ser adicionado após os except e é executado somente se nenhuma exceção ocorrer:
try:
bloco de código a ser monitorado
except TipoExceção1:
pass
except TipoExceção2:
pass
else:
código a executar quando não há exceções
O bloco finally é sempre executado, independentemente de exceções, e é útil para liberar recursos:
try:
bloco de código a ser monitorado
except TipoExceção:
pass
else:
código sem exceções
finally:
código sempre executado (ex.: fechar arquivos ou conexões)
Exemplo:
arquivo = None
try:
arquivo = open("dados.txt", "r", encoding="utf-8")
conteudo = arquivo.read().strip()
numero = int(conteudo) # Pode levantar ValueError se conteudo não for numérico
finally:
if arquivo is not None:
arquivo.close()
Para violar regras definidas pelo programador, use a instrução raise para levantar exceções explicitamente:
class Pessoa:
def __init__(self, nome, idade):
if not isinstance(nome, str):
raise TypeError("nome deve ser uma string")
if not isinstance(idade, int):
raise TypeError("idade deve ser um inteiro")
self.nome = nome
self.idade = idade
pessoa1 = Pessoa(12345, 30) # TypeError: nome deve ser uma string
pessoa2 = Pessoa("Carlos", "trinta") # TypeError: idade deve ser um inteiro
Exceções personalizadas podem ser criadas herdando de classes de exceção embutidas:
class ErroDeRecursoExaurido(Exception):
def __init__(self, mensagem="O recurso foi esgotado"):
super().__init__()
self.mensagem = mensagem
def __str__(self):
return "Exceção: %s" % self.mensagem
class ErroDeRede(IOError):
pass
raise ErroDeRecursoExaurido # Exceção: O recurso foi esgotado
raise ErroDeRede("Falha na conexão") # Exceção: Falha na conexão
A instrução assert verifica se uma condição é verdadeira; caso contrário, levanta AssertionError:
idade = "vinte"
assert isinstance(idade, int) # Levanta AssertionError se idade não for int
# Equivalente a:
if not isinstance(idade, int):
raise AssertionError
O uso de tratamento de exceções deve ser equiilbrado. Para erros previsíveis, utilize estruturas condicionais para prevenção:
entrada = input("Digite sua idade: ").strip()
if entrada.isdigit():
idade = int(entrada)
else:
print("Entrada inválida: insira um número.")
Para situações imprevisíveis, como falhas de rede, o tratamento de exceções é apropriado:
import requests
from requests.exceptions import ConnectTimeout
def obter_conteudo(url):
try:
resposta = requests.get(url, timeout=3)
conteudo = resposta.text
except ConnectTimeout:
print("Tempo de conexão esgotado.")
conteudo = None
except Exception:
print("Erro de rede inesperado.")
conteudo = None
return conteudo
obter_conteudo("https://www.example.com")