1.11. Tratamento de Exceções

Existem dois tipos de erros que normalmente ocorrem ao escrever programas. O primeiro, conhecido como erro de sintaxe, significa simplesmente que programador cometeu um erro na estrutura de um comando ou expressão. Por exemplo, é incorreto escrever um comado for e esquecer os dois pontos.

>>> for i in range(10)
SyntaxError: invalid syntax (<pyshell#61>, line 1)

Nesse caso, o interpretador Python descobriu que não pode concluir o processamento desta instrução, uma vez que não está em conformidade com as regras da linguagem. Erros de sintaxe são geralmente mais frequentes quando você estão aprendendo uma linguagem.

O outro tipo de erro, conhecido como erro lógico, denota uma situação onde o programa é executado, mas dá o resultado errado. Isso pode ser devido a um erro no algoritmo ou a um erro na sua tradução do algoritmo. Em alguns casos, erros lógicos levam a situações muito ruins como tentar dividir por zero ou tentar acessar um item de uma lista em que o índice do item está fora dos limites da lista. Neste caso, o erro lógico leva a um erro de execução que faz com que o programa termine. Esses tipos de erro em tempo de execução são geralmente chamados de exceções.

Na maioria das vezes, os programadores iniciantes simplesmente pensam em exceções como erros fatais em tempo de execução que causam o fim da execução. No entanto, a maioria das linguagens de programação fornecem uma maneira de lidar com esses erros que permitem ao programador algum tipo de intervenção, se assim desejarem. Além disso, os programadores podem criar suas próprias exceções se detectarem situações na execução do programa que as justifiquem.

Quando ocorre uma exceção, dizemos que ela foi “levantada”. Você pode “tratar” a exceção que foi levantada usando um comando try. Por exemplo, considere o seguinte fragmento de código que pergunta ao usuário para digitar um inteiro e, em seguida, chama a função raiz quadrada (sqrt) da biblioteca matemática (math). Se o usuário inserir um valor maior ou igual a para 0, a impressão mostrará a raiz quadrada. No entanto, se o usuário inserir um valor negativo, a função raiz quadrada irá reportar uma exceção do tipo ValueError.

>>> num = int(input("Digite um número inteiro: "))
Digite um número inteiro: -23
>>> print(math.sqrt(num))
Traceback (most recent call last):
  File "<pyshell#102>", line 1, in <module>
    print(math.sqrt(num))
ValueError: math domain error
>>>

Podemos lidar com essa exceção chamando a função print de dentro de um bloco try. Um bloco except correspondente “captura” a exceção e imprime uma mensagem de volta ao usuário caso uma exceção ocorra. Por exemplo:

>>> try:
       print(math.sqrt(num))
    except:
       print("Valor impróprio para raiz quadrada")
       print("Usando valor absoluto em seu lugar")
       print(math.sqrt(abs(num)))

Valor impróprio para raiz quadrada
Usando valor absoluto em seu lugar
4.79583152331
>>>

vai pegar o fato de que uma exceção é levantada por sqrt e vai em vez disso, imprimir as mensagens de volta para o usuário e usar o valor absoluto para ter certeza de que estamos pegando a raiz quadrada de um número não negativo. Isso significa que o programa não terminará, mas continuará a executar os comandos seguintes.

Também é possível para um programador causar uma exceção em tempo de execução usando o comando raise. Por exemplo, em vez de chamar a função raiz quadrada com um número negativo, poderíamos primeiro ter verificado o valor e, em seguida, levantar nossa própria exceção. O fragmento de código abaixo mostra o resultado da criação de uma nova exceção do tipo RuntimeError (erro em tempo de execução). Observe que o programa ainda terminaria, mas agora a exceção que causa o término é algo explicitamente criado pelo programador.

>>> if num < 0:
...    raise RuntimeError("Você não pode usar um valor negativo")
... else:
...    print(math.sqrt(num))
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
RuntimeError: Você não pode usar um valor negativo
>>>

Existem muitos tipos de exceção que podem ser levantados além do RuntimeError mostrado acima. Veja o manual de referência do Python para uma lista de todos os tipos de exceção disponíveis e de como criar suas próprias exceções.

Next Section - 1.12. Defining Functions