2.25. Tratamento de erros

A maioria dos problemas em tempo de execução no Python surgem como exceções – uma forma estruturada e com nome de reportar que algo correu mal. ValueError, TypeError, KeyError, OSError, MemoryError são todos exemplos; cada um é uma classe, e lançar uma para o código chamador que procura um tratador no código envolvente.

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 controlo salta para o bloco except em vez de propagar o erro. Se input_text era uma string inteira válida, o bloco except é ignorado.

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 faz a correspondência por ordem; o primeiro cuja classe de exceção se encaixa trata o problema. Capturar Exception (a classe base para quase tudo) trata qualquer erro; reserve isso para a camada mais externa de um programa onde a alternativa é uma falha.

Aviso

Um except: simples (sem classe após a palavra-chave) também captura KeyboardInterrupt – a exceção que o IDE envia quando prime o botão parar para interromper um script em execução. Um ciclo envolvido num except: pass simples engolirá a interrupção e continuará a executar, sem deixar forma de parar o script exceto um ciclo de energia.

Prefira except Exception: em vez de except: simples quando genuinamente precisa de capturar amplamente. KeyboardInterrupt herda de BaseException, não de Exception, por isso except Exception: mantém o botão de parar a funcionar.

2.25.1.1. Inspecionar 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 vinculada por as é válida apenas dentro do bloco except.

2.25.2. else e finally

Um bloco try tem dois extras opcionais.

else é executado apenas quando o try terminou sem lançar:

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

Colocar «o que fazer quando correu bem» em else mantém o bloco try restrito – apenas a linha que pode falhar pertence ao try.

finally é executado no final independentemente do que aconteça – quer o try tenha tido sucesso, lançado e sido tratado, ou lançado e esteja prestes a propagar:

try:
    do_work()
finally:
    cleanup()
Flow diagram showing the four possible paths through try / except / else / finally: success goes to else then finally; a caught exception goes to except then finally; an uncaught exception goes to finally then propagates.

finally executa sempre. else executa apenas no caminho sem exceção.

Para a maioria dos padrões de aquisição/libertação, prefira um gestor de contexto em vez de um par try / finally – o próprio recurso gere a sua limpeza.

2.25.3. Exceções incorporadas comuns

Uma lista breve das exceções que encontrará frequentemente:

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

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

  • KeyError – chave ausente num dict.

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

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

  • OSError – falha de sistema de ficheiros ou E/S.

  • MemoryError – heap esgotado. Num ambiente de execução com memória limitada, isto pode acontecer durante a operação normal – não apenas em casos patológicos.