6. Exceções
Vamos agora analisar as exceções.
![]() |
O primeiro script ilustra a necessidade de lidar com exceções.
Provocamos intencionalmente um erro para ver as informações produzidas pelo interpretador. A saída é a seguinte:
A linha 4 dá-nos:
- o tipo de exceção: ZeroDivisionError;
- a mensagem de erro associada: divisão ou módulo inteiro por zero. Está em inglês. Isto é algo que talvez queira alterar.
A regra essencial na programação é que devemos fazer tudo o que for possível para evitar falhas «incontroladas» como a acima referida. Mesmo em caso de erro, o programa deve terminar corretamente, fornecendo informações sobre o erro que ocorreu.
A sintaxe para o tratamento de exceções é a seguinte:
try:
actions susceptibles de lancer une exception
except [classe d'exception, ...]:
actions de gestion de l'exception
finally:
actions toujours exécutées qu'il y ait exception ou non
No bloco try, a execução das ações é interrompida assim que ocorre uma exceção. Neste caso, a execução continua com as ações na cláusula except.
O
except [MyException, ...]:
intercepta exceções do tipo MyException ou tipos derivados. Quando ocorre uma exceção num bloco try, o interpretador examina as cláusulas except associadas ao bloco try na ordem em que foram escritas. Ele pára na primeira cláusula except capaz de tratar a exceção que ocorreu. Se não encontrar nenhuma, a exceção é propagada de volta para o método chamador. Se esse método tiver um bloco try/except, a exceção é tratada novamente; caso contrário, continua a propagar-se pela cadeia de métodos chamados. Por fim, chega ao interpretador Python. O interpretador encerra então o programa em execução e exibe uma mensagem de erro do tipo mostrado no exemplo anterior. A regra é, portanto, que o programa principal deve capturar todas as exceções que possam propagar-se a partir dos métodos chamados.
Uma exceção contém informações sobre o erro que ocorreu. Estas informações podem ser recuperadas utilizando a seguinte sintaxe:
except MyException as informations:
information é uma tupla que contém as informações relacionadas com a exceção.
A sintaxe
except MyException, erreur:
atribui a mensagem de erro associada à exceção à variável error.
Para lançar uma exceção, utilize a sintaxe
raise MyException(param1, param2, ...)
onde MyException é, na maioria das vezes, uma classe derivada da classe Exception. Os parâmetros passados ao construtor da classe estarão disponíveis para a cláusula except das estruturas de tratamento de exceções.
Estes conceitos são ilustrados pelo seguinte script.
O script a seguir trata explicitamente os erros:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
Notas:
- linhas 6–9: tratam uma divisão por zero;
- linha 8: capturamos a exceção exata que ocorre;
- linha 11: devido à exceção que ocorreu, x não recebeu um valor e, portanto, não se alterou;
- linhas 15-19: fazemos o mesmo, mas capturamos uma exceção de nível superior do tipo Exception. Uma vez que a exceção ZeroDivisionError deriva da classe Exception, a cláusula except irá capturá-la;
- linhas 23–33: incluímos várias cláusulas except para lidar com vários tipos de exceção. Apenas uma cláusula except será executada, ou nenhuma, se a exceção não corresponder a nenhuma cláusula except;
- linhas 51–55: A cláusula except pode não ter argumentos. Neste caso, captura todas as exceções;
- linhas 59–62: introduzimos a exceção ValueError;
- linhas 66–69: recuperamos a informação contida na exceção;
- linhas 73–76: apresentam como lançar uma exceção;
- linhas 79–84: ilustram a utilização de uma classe de exceção personalizada, MyError;
- linhas 79–80: a classe MyError simplesmente herda da classe base Exception. Não acrescenta nada à sua classe base. Mas agora, pode ser explicitamente nomeada em cláusulas except;
- linhas 97–107: demonstram que, em Python, é possível lançar qualquer tipo de objeto, não apenas objetos derivados da classe Exception;
- Linhas 109–127: demonstram o uso da cláusula finally.
A saída no ecrã é a seguinte:
0 : integer division or modulo by zero
x=2
1 : integer division or modulo by zero
2 : (Exception) integer division or modulo by zero
3 : (ZeroDivisionError) integer division or modulo by zero
4 : il y a eu un probleme
5 : invalid literal for int() with base 10: 'x'
6 : invalid literal for int() with base 10: 'x'
7 : ('param1', 'param2', 'param3')
8 : ('info1', 'info2', 'info3')
9 : mon msg d'erreur
10 : pb...
11 : finally x=1
12 : exception
12 : finally x=None
Este novo script ilustra como as exceções são propagadas ao longo da cadeia de métodos de chamada:
Notas:
- Linhas 27–30: Na chamada main --> f1 --> f2 --> f3 (linha 28), a exceção MyError lançada por f3 propagar-se-á até main. Será então tratada pela cláusula except na linha 29;
- linhas 55–58: na chamada main → f4 → f5 → f6 (linha 56), a exceção MyError lançada por f6 propagar-se-á até main. Será então tratada pela cláusula except na linha 29. Desta vez, à medida que se propaga pela cadeia de métodos de chamada, a exceção MyError é enriquecida com informações adicionadas por cada método ao longo do caminho.
A saída no ecrã é a seguinte:
