Erros são só valores com atitude ruim
Quando algo dá errado em Python — divisão por zero, ler um arquivo que não existe, parsear um número ruim — o runtime cria um objeto de exceção e começa a desenrolar a pilha de chamadas até algo capturar. Se nada captura, seu programa termina e imprime um traceback.
Exceções não são ruins em si. São o jeito do Python sinalizar "não consigo continuar com esta operação; aqui está por quê". Seu trabalho é decidir, caso a caso, quais você sabe se recuperar e quais deve deixar escalar.
O formato básico
try:abre o bloco de código arriscado.except ValueError:captura essa exceção específica se for lançada dentro dotry.- Se nenhuma exceção dispara, o
excepté pulado inteiro.
Rode o snippet com 42 — funciona. Rode com hello — o handler roda.
Capturando exceções específicas
O Python tem uma hierarquia de tipos de exceção. Algumas que você vai encontrar com frequência:
ValueError— um valor estava errado de algum jeito (int("abc"), argumentos fora de alcance).TypeError— o tipo errado foi usado ("hi" + 3).KeyError— uma chave de dict não foi encontrada.IndexError— um índice de sequência estava fora de alcance.FileNotFoundError— um arquivo não existe.ZeroDivisionError— tentou dividir por zero.AttributeError— um objeto não tem o atributo pedido.
Capture o específico que você sabe tratar:
Você pode capturar várias exceções numa cláusula passando uma tupla:
Repare as e. Isso amarra o objeto de exceção a e para você inspecionar a mensagem ou atributos.
Evite capturar tudo
Um except: vazio captura literalmente qualquer coisa, inclusive KeyboardInterrupt (seu Ctrl-C) e saídas em nível de sistema. Não use.
except Exception: é um pouco melhor, mas ainda perigoso — engole bugs que você não antecipou e esconde a fonte real dos problemas:
# Don't do this without a really good reason.
try:
do_something()
except Exception:
pass
A escolha certa é quase sempre capturar a exceção específica da qual você sabe se recuperar. Se uma exceção que você não esperava chega ao topo do seu programa, o traceback te diz exatamente o que deu errado — isso é feature, não bug.
else e finally
A instrução try tem mais duas cláusulas opcionais:
elseroda se o blocotryterminou sem lançar.finallyroda não importa o quê — com ou sem exceção.
else é o lugar mais limpo para código "só em caso de sucesso" — você não quer que um bloco try faça mais do que a parte que pode falhar. finally é para limpeza que precisa rodar mesmo se o try falha: fechar um recurso, liberar um lock, restaurar estado.
Lançando exceções você mesmo
Use raise para sinalizar um erro no seu próprio código:
Escolha um tipo de exceção que bate com o que deu errado. Recorra aos embutidos primeiro — ValueError, TypeError, FileNotFoundError — antes de definir uma classe sua.
Definindo sua própria exceção
Quando os embutidos não capturam o significado, defina uma exceção customizada:
Herde de Exception (ou um embutido mais específico) e dê uma docstring à classe. Geralmente é tudo que você precisa. Exceções customizadas deixam quem chama capturar só o erro com significado no domínio.
raise ... from ...: exceções encadeadas
Quando uma exceção dispara outra, mantenha a corrente:
O from e anexa o erro original. Quando o traceback imprime, o Python mostra os dois — o ConfigError que apareceu e o FileNotFoundError que causou. Esse tipo de rastro é inestimável para debug.
Context managers: o jeito mais limpo de limpar
finally está bem, mas para recursos como arquivos, um context manager (o que o with usa) é quase sempre melhor:
# finally version
f = open("data.txt")
try:
data = f.read()
finally:
f.close()
# with version
with open("data.txt") as f:
data = f.read()
Os dois são seguros. A forma with é mais curta e se aplica automaticamente. Recorra a finally só quando está fazendo algo que a biblioteca padrão ainda não envolveu num context manager.
Quando não capturar
Capturar uma exceção é uma decisão — você está dizendo "sei tratar isso". Se você não sabe, deixe a exceção propagar. Código como este é quase sempre erro:
try:
do_work()
except Exception:
pass # silently ignore everything
Silenciar erros torna bugs invisíveis. É melhor quebrar barulhento do que mancar num estado inconsistente.
Fechando
try/exceptte deixa tratar erros dos quais você consegue se recuperar.- Capture exceções específicas, não
Exceptionem branco. raisesinaliza erros no seu próprio código.- Blocos
withsubstituem a maior parte da limpeza comfinally. - Na dúvida, deixe a exceção propagar.
A seguir: um tour pelos erros específicos que o Python mais dispara — KeyError, ValueError, ModuleNotFoundError e mais alguns — mais os hábitos de debug que resolvem eles rápido.
Perguntas frequentes
Como trato erros em Python?
Envolva código arriscado num bloco try e capture a exceção específica num bloco except: try: risky() except ValueError: .... O else opcional roda se nenhuma exceção ocorreu; finally roda de qualquer jeito, para limpeza.
Devo capturar Exception para ficar seguro?
Não. Um except: vazio ou except Exception: esconde bugs que você não antecipou. Capture a exceção específica da qual você sabe se recuperar, e deixe todo o resto propagar para você ver o problema real.
Qual a diferença entre raise e raise from?
raise NewError(...) lança uma nova exceção. raise NewError(...) from original mantém a exceção original anexada como causa, o que o Python mostra no traceback. Use from quando um erro de baixo nível dispara um de alto nível que você quer expor.