print("Olá, Mundo!)Cell In[1], line 1 print("Olá, Mundo!) ^ SyntaxError: EOL while scanning string literal
Todo programa, em algum momento, se depara com situações inesperadas: o usuário digita um texto onde se esperava um número, um arquivo não existe no caminho indicado, uma divisão por zero é tentada. Em vez de simplesmente travar, o Python possui um mecanismo estruturado para lidar com esses casos — as exceções.
Aprender a ler e tratar erros é uma das habilidades mais práticas da programação. Um bom código precisa ser defensivo: deve antecipar que as entradas podem estar mal formatadas e responder de forma controlada, sem interromper abruptamente a análise.
💡 Pense nas exceções como cláusulas de contingência em um contrato. Um contrato bem redigido não ignora a possibilidade de imprevistos — ele os prevê e especifica o que fazer em cada cenário. Da mesma forma, um bom programa não assume que tudo vai correr perfeitamente: ele define o que acontece quando algo dá errado.
A tabela abaixo resume os principais tipos de exceção que você pode encontrar ao programar em Python, com uma breve explicação e exemplos didáticos:
| Exceção | Quando ocorre | Exemplo |
|---|---|---|
SyntaxError |
Erro de sintaxe (regra de escrita) | print("olá) |
NameError |
Uso de nome/variável não definida | print(x) (sem definir x antes) |
TypeError |
Operação entre tipos incompatíveis | "1500" + 8300 |
ValueError |
Valor inadequado para uma operação | int("abc") |
ZeroDivisionError |
Divisão por zero | 100 / 0 |
IndexError |
Índice inexistente em lista | lista[99] com lista de 3 itens |
KeyError |
Chave inexistente em dicionário | dados["inflacao"] sem essa chave |
IndentationError |
Indentação incorreta | Código fora de alinhamento |
AttributeError |
Acesso a atributo que não existe | 100.upper() |
FileNotFoundError |
Arquivo não encontrado | open("dados.csv") sem o arquivo |
Esses são apenas alguns exemplos. Ler e interpretar corretamente as mensagens de erro é fundamental para depurar e evoluir seu código com confiança.
SyntaxError)O primeiro tipo de erro que você provavelmente irá encontrar ao programar em Python é o erro de sintaxe. Ele ocorre antes mesmo do programa começar a rodar: o Python tenta interpretar o código e encontra algo que não segue as regras da linguagem — como uma aspa faltando, um parêntese não fechado ou uma indentação incorreta.
O exemplo clássico:
print("Olá, Mundo!)Cell In[1], line 1 print("Olá, Mundo!) ^ SyntaxError: EOL while scanning string literal
O Python aponta exatamente a linha e o caractere onde detectou o problema. A mensagem EOL while scanning string literal significa que chegou ao fim da linha (End Of Line) sem encontrar o fechamento da string.
Toda mensagem de erro do Python segue a mesma estrutura:
File "...", line N: arquivo e linha onde o erro ocorreu.^ apontando o local exato.SyntaxError, ValueError, NameError.Sempre leia de baixo para cima: o tipo e a descrição são o ponto de partida para entender o problema.
SyntaxError não pode ser resolvido com try/except, pois o programa nem chega a ser executado. A única solução é revisar e corrigir o código.
Ao contrário dos erros de sintaxe, os erros de tempo de execução (runtime errors) ocorrem enquanto o programa já está rodando. O código está sintaticamente correto, mas algo inesperado acontece durante a execução — e aí o Python lança uma exceção.
ValueErrorUm ValueError ocorre quando uma função recebe um argumento do tipo certo, mas com um valor inadequado. O caso mais comum é tentar converter algo que não é número em inteiro ou decimal:
x = int(input("Digite um número: "))
print(f"O número digitado foi {x}")Como programadores, devemos ser cautelosos para garantir que os usuários estejam inserindo exatamente o que esperamos. Se executarmos esse programa e digitarmos “fea”, veremos: ValueError: invalid literal for int() with base 10: 'fea'.
Em outras palavras, a função int não consegue converter o texto “fea” em um número. Uma estratégia eficaz para corrigir esse possível erro é criar um tratamento de erros para garantir que o usuário se comporte conforme esperamos.
try e exceptPara lidar com exceções em tempo de execução, o Python oferece a estrutura try/except. A ideia é simples: colocamos no bloco try o código que pode falhar e no bloco except o que deve acontecer se a exceção ocorrer:
try:
<código que pode gerar exceção>
except <TipoDeExcecao>:
<o que fazer se a exceção ocorrer>Por exemplo:
try:
x = int(input("Digite um número: "))
print(f"O número digitado foi {x}")
except ValueError:
print("Valor inválido. Por favor, digite um número inteiro.")Se o usuário digitar "dez" em vez de 10, o int() lançaria um ValueError. Com try/except, capturamos esse erro e exibimos uma mensagem amigável em vez de travar o programa.
try
⚠️ Uma boa prática é colocar dentro do try apenas a linha que pode falhar, não o bloco inteiro. Isso evita capturar exceções de linhas que não têm nada a ver com o erro esperado.
NameError com try/exceptNote que essa ainda não é a melhor forma de implementar esse código, pois estamos tentando executar duas linhas de código. Veja o que acontece se colocarmos o print fora do try:
try:
x = int(input("Digite um número: "))
except ValueError:
print("Valor inválido. Por favor, digite um número inteiro.")
print(f"O número digitado foi {x}")Observe que, embora essa versão siga a boa prática de colocar no try apenas a linha que pode falhar, ela introduz um novo problema. Se o usuário digitar algo inválido, ocorre um ValueError, que é tratado pelo except. No entanto, logo depois disso, o programa tenta executar print(f"O número digitado foi {x}").
Nesse caso, aparece um NameError, pois a variável x não chegou a ser criada. Isso acontece porque, em x = int(input("Digite um número: ")), o Python primeiro avalia o lado direito da atribuição — isto é, tenta executar int(input(...)). Somente se essa etapa der certo o valor será atribuído a x.
Se a conversão para inteiro falhar, a atribuição nunca acontece. Portanto, ao chegar no print, o nome x ainda não existe na memória. É exatamente para resolver esse tipo de situação que o bloco else é útil: ele garante que o código que depende do sucesso do try só será executado quando nenhuma exceção ocorrer.
elseO bloco else em uma estrutura try/except executa somente se nenhuma exceção ocorreu. Ele é o lugar certo para o código que depende do sucesso do try:
try:
x = int(input("Digite um número: "))
except ValueError:
print("Valor inválido. Por favor, digite um número inteiro.")
else:
print(f"O número digitado foi {x}")Observe que, se nenhuma exceção ocorrer, o programa executará o bloco else. Ao rodar o código e digitar 10, por exemplo, a conversão será bem-sucedida e o valor será exibido normalmente. Já ao digitar "dez", a exceção será capturada pelo except, evitando que o programa quebre de forma inesperada.
Embora essa versão já seja mais segura, ainda há espaço para melhorar a experiência do usuário. No estado atual, se a entrada for inválida, o programa apenas exibe a mensagem de erro e termina. Em muitos casos, o comportamento ideal é dar ao usuário uma nova chance, repetindo a solicitação até que ele forneça um número inteiro válido.
Para isso, podemos combinar o tratamento de exceções com um loop, criando um mecanismo de validação que continua pedindo a entrada correta até que a conversão seja feita com sucesso.
elseUm padrão muito comum é combinar while True com try/except/else para continuar pedindo entrada até o usuário fornecer um valor válido:
while True:
try:
x = int(input("Digite um número: "))
except ValueError:
print("Valor inválido. Por favor, digite um número inteiro.")
else:
break
print(f"O número digitado foi {x}")O comando while True cria um laço que continuará pedindo a entrada do usuário indefinidamente, até que uma entrada válida seja fornecida.
Quando o usuário digita um valor correto, o break interrompe o loop e o programa segue para a próxima etapa, exibindo o resultado. Dessa forma, se o usuário errar, ele recebe uma mensagem de orientação e tem novas chances de acertar, tornando a experiência mais amigável e robusta. Podemos melhorar o código da seguinte maneira:
while True:
try:
x = int(input("Digite um número: "))
break
except ValueError:
print("Valor inválido. Por favor, digite um número inteiro.")
print(f"O número digitado foi {x}")A combinação de try, except, else e break se torna especialmente poderosa quando encapsulada em funções reutilizáveis.
def main():
x = obter_inteiro()
print(f"O número digitado foi {x}")
def obter_inteiro():
while True:
try:
x = int(input("Digite um número: "))
except ValueError:
print("Valor inválido. Por favor, digite um número inteiro.")
else:
break
return x
main()Observe que, ao criar uma função para obter um número inteiro, tornamos o programa mais organizado e reutilizável. Agora, a lógica principal do programa se resume a poucas linhas, facilitando a leitura e a manutenção.
Ainda assim, sempre é possível aprimorar o código. Que outras melhorias poderiam ser feitas para tornar essa função ainda mais robusta, flexível ou amigável para o usuário?
def main():
x = obter_inteiro()
print(f"O número digitado foi {x}")
def obter_inteiro():
while True:
try:
x = int(input("Digite um número: "))
except ValueError:
print("Valor inválido. Por favor, digite um número inteiro.")
else:
return x
main()Note que o comando return não apenas encerra o loop, mas também devolve o valor desejado para quem chamou a função. Algumas pessoas podem argumentar que seria possível obter o mesmo resultado de outras formas, como por exemplo:
def main():
x = obter_inteiro()
print(f"O número digitado foi {x}")
def obter_inteiro():
while True:
try:
return int(input("Digite um número: "))
except ValueError:
print("Valor inválido. Por favor, digite um número inteiro.")
main()passÀs vezes, queremos capturar uma exceção mas não fazer nada — simplesmente continuar o programa sem exibir mensagem de erro. Para isso usamos pass:
try:
<código que pode falhar>
except <Exceção>:
pass # ignora o erro silenciosamenteO pass é útil quando o comportamento correto diante de um erro é simplesmente tentar de novo (em um loop) ou pular aquele item.
pass vs. mensagem de erro
Use pass quando o erro é esperado e ignorá-lo é o comportamento correto (como pular entradas inválidas em uma lista). Prefira except ... : print(...) quando o erro é inesperado e o usuário precisa ser informado. Nunca use pass apenas para “silenciar” um erro que você não entendeu — isso esconde problemas reais.
def main():
x = obter_inteiro()
print(f"O número digitado foi {x}")
def obter_inteiro():
while True:
try:
return int(input("Digite um número: "))
except ValueError:
pass
main()Note que o código ainda funciona, mas não informa repetidamente ao usuário qual foi o erro cometido. Em algumas situações, é importante ser claro e mostrar ao usuário qual erro ocorreu; em outras, pode ser suficiente apenas pedir a entrada novamente, sem exibir mensagens.
Uma última melhoria interessante para a função obter_inteiro é permitir que o texto do prompt seja personalizado. Assim, não dependemos de um texto fixo dentro da função e tornamos o código mais flexível e reutilizável. Modifique sua implementação para aceitar um parâmetro de prompt.
def main():
x = obter_inteiro("Digite um número: ")
print(f"O número digitado foi {x}")
def obter_inteiro(prompt):
while True:
try:
return int(input(prompt))
except ValueError:
pass
main()Você pode aprender mais na documentação oficial do Python sobre o comando pass.
Suponha que você recebeu um CSV com dados mensais de inflação (IPCA). A coluna “ipca_bruto” deveria ser numérica, mas veio com problemas:
# Série do IPCA com valores mal formatados (dados "sujos")
ipca_bruto = ["4,62", "3,15", ".", "5,79", "-", "4,31", "", "3.72", "n/d", "6.50", " 4.83 "]
ipca_limpo = []
for valor in ipca_bruto:
try:
ipca_limpo.append(float(valor.strip().replace(",", ".")))
except ValueError:
pass # ignora valores não numéricas sem interromper o loop
print(f"Valores originais: {len(ipca_bruto)}")
print(f"Valores válidos: {len(ipca_limpo)}")
print(f"Valores ignorados: {len(ipca_bruto) - len(ipca_limpo)}")
print(f"IPCA médio (válidos): {sum(ipca_limpo) / len(ipca_limpo):.2f}%")Valores originais: 11
Valores válidos: 7
Valores ignorados: 4
IPCA médio (válidos): 4.70%
raise Em algumas situações, você pode querer interromper a execução do seu programa de forma controlada, lançando uma exceção quando uma condição indesejada ocorre. Para isso, usamos a palavra-chave raise.
No exemplo a seguir, a função calcular_raiz_quadrada() lança uma exceção ValueError se o número fornecido for negativo, garantindo que apenas valores válidos sejam processados:
def calcular_raiz_quadrada(numero):
if numero < 0:
raise ValueError("O número deve ser positivo")
return numero ** 0.5
valor = float(input("Digite um número: "))
resultado = calcular_raiz_quadrada(valor)
print(f"A raiz quadrada de {valor} é {resultado}")Além de utilizar as exceções já existentes no Python, também podemos criar nossas próprias exceções personalizadas para lidar com situações específicas do nosso programa. Para isso, basta criar uma nova classe que herda de Exception. Assim, conseguimos definir mensagens e comportamentos sob medida para os nossos casos de uso, tornando o tratamento de erros ainda mais claro e organizado:
def verificar_valor(valor):
if valor < 0:
raise Exception("O número não pode ser negativo!")
verificar_valor(-5)Um mesmo bloco try pode capturar diferentes tipos de exceção, cada um com seu próprio tratamento:
try:
<código>
except TipoA:
<tratamento para TipoA>
except TipoB:
<tratamento para TipoB>No exemplo a seguir, o bloco try tenta executar a divisão de dois números fornecidos pelo usuário. Se o usuário tentar dividir por zero, o except ZeroDivisionError captura essa exceção e exibe uma mensagem de erro. Além disso, se o usuário digitar algo que não seja um número, o except ValueError captura essa exceção e exibe uma mensagem de erro apropriada.
try:
x = int(input("Digite um número: "))
y = int(input("Digite outro número: "))
resultado = x / y
print(f"O resultado é: {resultado}")
except ZeroDivisionError:
print("Erro: Não é possível dividir por zero!")
except ValueError:
print("Erro: Entrada inválida! Por favor, digite um número.")Note que podemos capturar vários tipos ao mesmo tempo com uma tupla:
except (TipoA, TipoB):
<tratamento comum para ambos>try:
x = int(input("Digite um número: "))
y = int(input("Digite outro número: "))
resultado = x / y
print(f"O resultado é: {resultado}")
except (ZeroDivisionError, ValueError):
print("Erro: Certifique-se de digitar apenas números e que o divisor não seja zero.")O código abaixo contém três erros — um SyntaxError, um NameError e um ValueError. Identifique e corrija cada um deles:
def calcular_variacao(v_inicial, v_final)
variacao = (v_final - v_inicial) / v_inicial * 100
return variacao
pib_2022 = float("8.900,00")
pib_2023 = 9250.0
resultado = calcular_variacao(pib_2022, PIB_2023)
print(f"Variação do PIB: {resultado:.2f}%")Escreva uma função ler_taxa(prompt) que solicite ao usuário uma taxa de juros entre 0% e 100%. A função deve:
try/except para capturar ValueError se a entrada não for numérica.else para verificar se o valor está no intervalo permitido, pedindo novamente caso contrário.10.5 → retorna 0.105).Dada a lista abaixo com dados de exportações brasileiras (em US$ bilhões), alguns valores estão corrompidos. Escreva um programa que, usando try/except/pass:
exportacoes = ["32.1", "28.7", "N/A", "35.4", "erro", "29.8",
"31.2", "--", "33.6", "27.9", "34.1", "30.5"]Uma planilha de preços de commodities contém o seguinte dicionário. Escreva um programa que tente acessar cada chave de uma lista de consultas, capturando KeyError para as chaves inexistentes e ValueError para valores não numéricos, exibindo uma mensagem específica para cada caso.
commodities = {
"soja": "117.50",
"milho": "48.20",
"cafe": "pendente",
"petroleo": "88.75",
}
consultas = ["soja", "milho", "cafe", "algodao", "petroleo", "trigo"]Expanda a função processar_serie() definida nesta aula para aceitar um parâmetro opcional limiar_invalidos (padrão: 0.3). Se a proporção de dados inválidos exceder esse limiar, a função deve lançar um ValueError com uma mensagem descritiva em vez de retornar o resultado parcial. Teste com a série ["1.2", "n/d", "n/d", "n/d", "0.8"].