2.25. Tratamento de erros

A maioria dos problemas em tempo de execução no Python se manifesta como exceções – uma forma nomeada e estruturada de relatar que algo deu errado. ValueError, TypeError, KeyError, OSError, MemoryError são todos exemplos; cada um é uma classe, e lançar uma delas interrompe a chamada atual e procura um tratador no código ao redor.

2.25.1. try / except

Envolva um bloco de código em try para capturar qualquer exceção que ele lance:

try:
    n = int(input_text)
except ValueError:
    n = 0

Se a conversão int(...) falhar, o controle salta para o bloco except em vez de propagar o erro adiante. Se input_text for uma string de inteiro válida, o bloco except é pulado.

Um único try pode ter vários blocos except, cada um capturando um tipo diferente de erro:

try:
    value = data[key]
except KeyError:
    value = None
except TypeError:
    value = -1

O Python casa em ordem; o primeiro cuja classe de exceção se encaixa trata o problema. Capturar Exception (a classe base de quase tudo) trata qualquer erro; reserve isso para a camada mais externa de um programa, onde a alternativa seria uma falha.

Aviso

Um except: simples (sem classe após a palavra-chave) também captura KeyboardInterrupt – a exceção que a IDE envia quando você pressiona o botão stop para interromper um script em execução. Um laço envolto em um except: pass simples vai engolir a interrupção e continuar rodando, sem deixar nenhuma forma de parar o script a não ser desligando e ligando a energia.

Prefira except Exception: em vez de um except: simples quando você realmente precisar capturar de forma ampla. KeyboardInterrupt herda de BaseException, não de Exception, então except Exception: deixa o botão stop funcionando.

2.25.1.1. Inspecionando a exceção

Para ler a mensagem associada a uma exceção, nomeie-a com as:

try:
    f = open("data.txt")
except OSError as e:
    print("could not open file:", e)

A variável associada por as só é válida dentro do bloco except.

2.25.2. else e finally

Um bloco try tem dois extras opcionais.

O else é executado somente quando o try termina sem lançar uma exceção:

try:
    value = compute()
except ValueError:
    print("bad input")
else:
    print("got", value)

Colocar “o que fazer quando deu certo” no else mantém o bloco try enxuto – apenas a linha que pode falhar pertence ao try.

O finally é executado ao final aconteça o que acontecer – quer o try tenha tido sucesso, quer tenha lançado e sido tratado, quer tenha lançado e esteja prestes a propagar:

try:
    do_work()
finally:
    cleanup()
Diagrama de fluxo mostrando os quatro caminhos possíveis através de try / except / else / finally: sucesso vai para else e depois finally; uma exceção capturada vai para except e depois finally; uma exceção não capturada vai para finally e depois propaga.

O finally sempre é executado. O else só é executado no caminho sem exceção.

Para a maioria dos padrões de adquirir/liberar, prefira um gerenciador de contexto em vez de um par try / finally – o próprio recurso gerencia sua limpeza.

2.25.3. Exceções embutidas comuns

Uma lista curta das exceções que você encontrará com frequência:

  • ValueError – tipo certo, valor errado (bytes([300]) – 300 é do tipo certo, mas está fora do intervalo válido de bytes de 0..255).

  • TypeError – tipo totalmente errado (len(42)).

  • KeyError – chave ausente em um dict.

  • IndexError – índice além do fim de uma sequência.

  • AttributeError – acessar um atributo que não existe ("abc".foo).

  • OSError – uma falha de sistema de arquivos ou de E/S.

  • MemoryError – ficou sem heap. Em um ambiente de execução com memória restrita, isso pode acontecer durante a operação normal – não apenas em casos patológicos.