Python também suporta excepções*. As excepções em Python são bastante usuais de outras linguagens mas têm algumas características especiais.
Começemos pela sua sintaxe:
try:
#statements1
except [expression [ , target] ]:
#statements2
[else:
#statements3]
A semântica é a usual de outras linguagens excepto aqui a keyword catch for substituída por except. O corpo de cada exception handler é executado apenas se expression na cláusula except correspondente estiver de acordo com o objecto excepção que está a ser propagado. Desta forma, expression deve avaliar sempre para uma classe ou tuplo de classes. O target opcional corresponde ao nome que é ligado ao objecto excepção para que este possa ser manipulado dentro do corpo do exception handler.
Exemplo:
try:
1/0
except ZeroDivisionError:
print 'caught divide by 0 attempt'
Podemos ter um except sem expressão e, nesse caso, esse handler é executado para qualquer tipo de excepção.
Tal como nos while's e for's, o corpo da cláusula opcional else é executada apenas quando o corpo dentro do try não lança qualquer tipo de excepção e quando a sua execução não termina por break, return ou continue.
Existe um outro tipo de construção sintáctica conhecida como try/finally e a sua sintaxe é a seguinte:
try:
#statements
finally:
#statements
(não pode ter else)
O corpo do finally é sempre executado depois do corpo do try independentemente de este lançar, ou não, excepções. Note-se que até à versão 2.5 do Python as duas construções sintáticas existiam e não podiam ser misturadas, i.e. esta última variante não podia ter else ou excepts. Felizmente, a partir da versão 2.5 existe apenas uma construção na forma:
try:
...
except:
exception handler
finally:
clean-up code
Quanto à hierarquia de tipos de excepções, penso que não é necessário divulgar aqui mas posso dizer que é bastante complexa e completa.
Por último, para lançar explícitamente uma excepção deve-se usar a keyword raise.
Usar raise sem mais nada permite relançar a mesma excepção que fez com que o fluxo de execução fosse parar ao exception handler. Assim, esta construção apenas faz sentido dentro do corpo de um exception handler ou dentro de uma função chamada por um exception handler.
No caso geral, a sintaxe é a seguinte:
raise [expressao1 [ , expressao2 ] ]
expressao1 pode avaliar para uma classe, caso onde expressao2 se presente é usada como argumento para construir uma instância da classe cujo valor é expressao1. No entanto, expressao1 pode também ser uma instância de uma qualquer classe e, nesse caso, expressão2 não pode estar presente, sendo essa instância lançada como excepção. Exemplo:
def crossProduct(seq1, seq2):
if not seq1 or not seq2:
raise ValueError, "Sequence arguments must be non-empty"
return [(x1, x2) for x1 in seq1 for x2 in seq2]
*Acho que teria menos trabalho se escrevesse um blog sobre aquilo que o python não suporta.
Blog em português onde relato a minha aprendizagem de Python. Sendo um blog, ele deve ser lido de baixo para cima e é escrito orientado a uma audiência com alguns conhecimentos de programação. Não tentando ser uma fonte exaustiva de conhecimento sobre Python, pode, no entanto, servir como crash course a esta linguagem.