try/except: capturando o erro antes que ele derrube o programa
Um programa que aceita entrada de usuário vai, cedo ou tarde, receber algo inesperado. A pergunta não é se isso vai acontecer, é o que o programa faz quando acontece.
Estudar esta lição interativa →Um programa que converte texto digitado por um usuário em número, com int(texto), funciona perfeitamente enquanto o texto for mesmo um número. Mas cedo ou tarde alguém vai digitar "abc", ou deixar o campo vazio, e int("abc") derruba o programa inteiro com ValueError: invalid literal for int() with base 10: 'abc'. A pergunta não é se isso vai acontecer num programa real, é o que o programa faz quando acontece.
entradas = ["10", "abc", "25"]
for entrada in entradas:
try:
numero = int(entrada)
print(f"Convertido: {numero}")
except ValueError:
print(f"'{entrada}' não é um número válido, pulando.")
print("Programa continuou até o fim.")O programa continua rodando mesmo com uma entrada inválida no meio.
try marca um bloco "arriscado", que pode falhar; except TipoDeErro: marca o que fazer se, e somente se, aquele tipo específico de erro acontecer dentro do try. Se nenhum erro acontecer, o bloco except nem chega a rodar, e o programa segue normalmente depois do try.
Pense num try/except como a rede de segurança de um circo: o artista tenta o número arriscado (o try) sabendo que, se cair, a rede (o except) o pega antes de chegar no chão. Sem a rede, uma queda encerraria o espetáculo inteiro; com ela, o show continua.
Dois blocos extras completam a estrutura: else roda só se o try terminou sem nenhum erro; finally roda sempre, com erro ou sem erro, útil para uma limpeza que precisa acontecer de qualquer jeito, como encerrar uma conexão. (Para arquivos o Python tem uma forma ainda melhor, o with, que fecha o arquivo sozinho; você o encontra quando for trabalhar com arquivos.)
try:
resultado = 10 / 2
print(f"Resultado: {resultado}")
except ZeroDivisionError:
print("Não é possível dividir por zero.")
else:
print("Divisão feita sem nenhum erro.")
finally:
print("Isto roda sempre, com erro ou sem erro.")É tentador escrever só except:, sem especificar o tipo, para "pegar qualquer coisa que der errado". Evite isso: um except: genérico também esconde erros de programação de verdade (um nome digitado errado, uma lógica quebrada), fazendo o programa continuar rodando de um jeito silenciosamente errado, em vez de avisar sobre um bug que precisava ser corrigido. Há ainda um agravante: o except: sem tipo também captura o KeyboardInterrupt (o Ctrl+C) e o SystemExit, e o programa deixa de poder ser interrompido. Capturar except ValueError: especificamente deixa claro qual falha você está mesmo esperando e tratando.
Se o código dentro do try lançar um ZeroDivisionError, mas o seu except só captura ValueError, o programa não é protegido: o ZeroDivisionError simplesmente não é pego por aquele bloco, e derruba o programa do mesmo jeito, como se o try/except nem existisse para esse caso. Sempre confira se o tipo de exceção no except é realmente o tipo que a operação arriscada pode lançar.
dividendo = 10
divisor = 0
resultado = dividendo / divisor
print(resultado)Adicione try/except ao redor da divisão.