Python Try...Except
Aprenda os blocos try, except, else e finally do Python com exemplos claros. Trate ZeroDivisionError, ValueError, FileNotFoundError e muito mais.
Quando o Python encontra um erro em tempo de execução, ele lança uma exceção — um objeto que representa o que deu errado. Sem nenhum tratamento, uma exceção encerra o programa imediatamente. A instrução try...except permite capturar essas exceções, responder a elas de forma elegante e manter o programa em execução.
Este capítulo aborda:
- O bloco
try/except— capturando uma exceção específica - Capturando detalhes da exceção com
as - Múltiplas cláusulas
excepte capturando várias exceções ao mesmo tempo - O bloco
else— código que só é executado quando nenhuma exceção ocorre - O bloco
finally— código de limpeza que sempre é executado - Exceções integradas comuns e quando elas ocorrem
- Relançando exceções
- Boas práticas e erros comuns
O bloco try...except básico
Envolva o código que pode falhar em um bloco try. Se o Python lançar uma exceção, a execução salta para o bloco except correspondente em vez de encerrar o programa.
Saída:
Error: division by zeroO Python tenta a divisão, lança ZeroDivisionError e o bloco except trata o erro. A cláusula as e vincula o objeto de exceção a e para que você possa inspecionar ou registrar a mensagem.
Se o bloco try for concluído com sucesso, o bloco except é completamente ignorado.
Capturando um tipo específico de exceção
Sempre nomeie o tipo de exceção que você espera. Capturar um tipo nomeado deixa sua intenção clara e evita ocultar acidentalmente bugs não relacionados.
try:
number = int("abc")
except ValueError as e:
print(f"Could not convert: {e}")Saída:
Could not convert: invalid literal for int() with base 10: 'abc'int("abc") lança ValueError porque "abc" não é um inteiro válido. Especificar ValueError na cláusula except significa que qualquer outra exceção inesperada ainda será propagada e aparecerá como erro, em vez de ser silenciosamente ignorada.
Múltiplas cláusulas except
Um único bloco try pode ter várias cláusulas except — o Python as verifica de cima para baixo e executa a primeira correspondência.
def safe_index(items, index):
try:
return items[index]
except IndexError:
print("Index out of range.")
except TypeError:
print("Index must be an integer.")
safe_index([1, 2, 3], 10) # IndexError
safe_index([1, 2, 3], "a") # TypeErrorSaída:
Index out of range.
Index must be an integer.A ordem importa: coloque tipos de exceção mais específicos antes dos mais amplos para que o tratador específico seja executado primeiro.
Capturando múltiplas exceções em uma única cláusula
Quando duas ou mais exceções merecem a mesma resposta, agrupe-as em uma tupla:
try:
value = int("not-a-number")
except (ValueError, TypeError) as e:
print(f"Input error: {e}")Saída:
Input error: invalid literal for int() with base 10: 'not-a-number'O bloco else
O bloco else é executado somente quando o bloco try é concluído sem lançar nenhuma exceção. Use-o para código que deve ser executado em caso de sucesso, mas que não precisa de proteção contra erros:
try:
result = 10 / 2
except ZeroDivisionError:
print("Cannot divide by zero.")
else:
print(f"Division succeeded. Result: {result}")Saída:
Division succeeded. Result: 5.0Manter a lógica do caminho de sucesso no else (em vez de no final do try) evita capturar acidentalmente exceções que o próprio código do caminho de sucesso possa lançar.
O bloco finally
O bloco finally é executado independentemente do resultado — seja o bloco try bem-sucedido, uma exceção capturada ou uma exceção propagada sem ser capturada. Use-o para limpeza: fechar arquivos, liberar bloqueios ou desconectar de um banco de dados.
try:
result = 10 / 0
except ZeroDivisionError:
print("Error caught.")
finally:
print("This always runs — cleanup goes here.")Saída:
Error caught.
This always runs — cleanup goes here.Mesmo que você comente o bloco except, o finally ainda é executado antes do Python propagar a exceção.
Estrutura completa de relance
try:
# code that may raise an exception
except SomeException as e:
# handle the exception
except (AnotherError, YetAnother):
# handle either of these
else:
# runs only when try succeeded
finally:
# always runsExceções integradas comuns
| Exceção | Quando ocorre |
|---|---|
ZeroDivisionError | Divisão ou módulo por zero |
ValueError | Tipo correto, valor errado (ex.: int("abc")) |
TypeError | Operação aplicada ao tipo errado |
IndexError | Índice de sequência fora do intervalo |
KeyError | Chave de dicionário não encontrada |
FileNotFoundError | Arquivo ou diretório não existe |
AttributeError | Objeto não possui tal atributo |
ImportError | Módulo não pode ser importado |
NameError | Nome de variável não está definido |
Todas essas exceções herdam da classe base Exception. Você pode capturar Exception para tratar qualquer uma delas em uma única cláusula, mas prefira tipos específicos sempre que possível.
Tratando um arquivo ausente
try:
with open("data.txt", "r") as file:
content = file.read()
except FileNotFoundError:
print("Error: File not found.")Saída (quando data.txt não existe):
Error: File not found.Relançando uma exceção
Às vezes, você deseja registrar uma exceção ou fazer uma limpeza parcial, mas ainda permitir que ela se propague para o chamador. Use um raise simples dentro de um bloco except:
def process():
try:
result = 10 / 0
except ZeroDivisionError:
print("Logging error...")
raise # re-raises the original ZeroDivisionError
try:
process()
except ZeroDivisionError as e:
print(f"Outer handler caught: {e}")Saída:
Logging error...
Outer handler caught: division by zeroO raise simples preserva o traceback original para que a depuração não seja mais difícil do que sem o tratador.
Capturando a classe base Exception
Você pode usar Exception como um captura-tudo para qualquer erro que não encerre o sistema:
try:
result = 10 / 0
except Exception as e:
print(f"An error occurred: {type(e).__name__}: {e}")Saída:
An error occurred: ZeroDivisionError: division by zerotype(e).__name__ fornece o nome específico da classe mesmo quando você captura via a classe base. Isso é útil em tratadores de nível superior onde você deseja registrar todos os erros inesperados.
Bare except — e por que evitá-lo
Um bare except (sem nenhum tipo de exceção) captura literalmente tudo, incluindo KeyboardInterrupt (Ctrl+C) e SystemExit, tornando o programa difícil de interromper:
# Avoid this pattern
try:
result = 10 / 0
except:
print("Some error occurred")Prefira except Exception se precisar de uma captura ampla, pois isso ainda permite que KeyboardInterrupt e SystemExit se propaguem normalmente.
Boas práticas
- Seja específico. Capture o tipo de exceção mais restrito que fizer sentido.
- Não silencie exceções. No mínimo, registre o erro; nunca deixe um bloco
exceptvazio. - Use
elsepara o código do caminho de sucesso. Isso mantém o blocotryo menor possível. - Use
finallypara limpeza. Ou, ainda melhor, use uma instruçãowith— veja Python with Statement. - Evite
bare except. Useexcept Exceptionse precisar de uma rede ampla. - Relance quando apropriado. Se você não puder tratar completamente o erro, deixe-o se propagar com
raise.
Para lançar exceções deliberadamente e criar suas próprias classes de exceção, veja Python raise and Custom Exceptions.