• Nenhum resultado encontrado

Exceções

No documento python24 (páginas 59-62)

Mesmo que um comando ou expressão estejam sintaticamente corretos, talvez ocorra um erro na hora de sua execução. Erros detectados durante a execução são chamados exceções e não são necessariamente fatais. Logo veremos como tratá-las em programas Python. A maioria das exceções não são tratadas e acabam resultando em mensagens de erro:

>>> 10 * (1/0)

Traceback (most recent call last): File "<stdin>", line 1, in ?

ZeroDivisionError: integer division or modulo by zero >>> 4 + spam*3

Traceback (most recent call last): File "<stdin>", line 1, in ?

NameError: name ’spam’ is not defined >>> ’2’ + 2

Traceback (most recent call last): File "<stdin>", line 1, in ?

é impresso como parte da mensagem . Os tipos no exemplo são: ZeroDivisionError, NameErrore TypeError. A string impressa como sendo o tipo da exceção é o nome interno da exceção que ocorreu. Isso é verdade para todas exceções pré-definidas em Python, mas não é necessariamente verdade para exceções definidas pelo usuário.

O resto da linha é um detalhamento que depende do tipo da exceção ocorrida e sua causa.

A parte anterior da mensagem de erro apresenta o contexto onde ocorreu a exceção. Essa informação é denominada stack traceback (N.d.T: rastreamento da pilha para trás). Em geral, contém uma lista de linhas do código fonte, sem apresentar, no entanto, valores lidos da entrada padrão.

O documentoReferência da Biblioteca Pythonlista as exceções pré-definidas e seus significados.

8.3

Tratamento de Exceções

É possível escrever programas que tratam exceções específicas. Observe o exemplo seguinte, que pede dados ao usuário até que um inteiro válido seja fornecido, ainda permitindo que o programa seja interrompido (utilizando

Control-Cou seja lá o que for que o sistema operacional suporte). Note que uma interrupção gerada pelo usuário será sinalizada pela exceçãoKeyboardInterrupt.

>>> while True:

... try:

... x = int(raw_input("Entre com um número: "))

... break

... except ValueError:

... print "Opa! Esse número não é válido. Tente de novo..." ...

A construçãotryfunciona da seguinte maneira:

• Primeiramente, a cláusula try (o conjunto de comandos entre as palavras-reservadastryeexcept) é executado.

• Se não for gerada exceção, a cláusula except é ignorada e termina a execução da construçãotry.

• Se uma execução ocorre durante a execução da cláusulatry, os comandos remanescentes na cláusula são ignorados. Se o tipo da exceção ocorrida tiver sido previsto junto àlguma palavra-reservadaexcept, então essa cláusula será executada. Ao fim da cláusula também termina a execução dotrycomo um todo.

• Se a exceção ocorrida não foi prevista em nenhum tratadorexceptda construçãotryem que ocorreu, então ela é entregue a uma construçãotrymais externa. Se não existir nenhum tratador previsto para tal exceção (chamada unhandled exception), a execução encerra com uma mensagem de erro.

A construçãotrypode ter mais de uma cláusulaexceptpara especificar múltiplos tratadores para diferentes exceções. No máximo um único tratador será ativado. Tratadores só são sensíveis as exceções levantadas no interior da cláusulatry, e não que tenha ocorrido no inteiror de outro tratador num mesmotry. Um tratador pode ser sensível a múltiplas exceções, desde que as especifique em uma tupla:

... except (RuntimeError, TypeError, NameError): ... pass

A última cláusulaexceptpode omitir o nome da exceção, servindo como uma máscara genérica. Utilize esse recurso com extrema cautela, uma vez que isso pode esconder errors do programador e do usuário. Também pode ser utilizado para imprimir uma mensagem de erro, ou re-levantar (re-raise) a exceção de forma que um “chamador” também possa tratá-la.

import sys try:

f = open(’myfile.txt’) s = f.readline() i = int(s.strip())

except IOError, (errno, strerror):

print "I/O error(%s): %s" % (errno, strerror) except ValueError:

print "Could not convert data to an integer." except:

print "Unexpected error:", sys.exc_info()[0] raise

A construçãotry. . .exceptpossui uma cláusula else opcional, que quando presente, deve ser colocada depois de todas as outras cláusulas. É útil para um código que precisa ser executado se nenhuma exceção foi levantada. Por exemplo:

for arg in sys.argv[1:]: try:

f = open(arg, ’r’) except IOError:

print ’cannot open’, arg else:

print arg, ’has’, len(f.readlines()), ’lines’ f.close()

Este recurso é melhor do que simplesmente adicionar o código doelseao corpo da cláusulatry, pois mantém as exceções levantadas noelsenum escopo diferente de tratamento das exceções levantadas na cláusulatry. Quando uma exceção ocorre, ela pode estar associada a um valor chamado argumento da exceção. A presença e o tipo do argumento dependem do tipo da exceção.

A cláusula except pode especificar uma variável depois do nome (ou da tupla de nomas) exceção. A variável é ligada à instância dela com os argumentos armazenados eminstance.args. Por conveniência, a instância define os métodos__getitem__e__str__para que os argumentos possam ser acessados sem necessidada de recorrer a.args.

>>> try:

... raise Exception(’spam’, ’eggs’)

... except Exception, inst:

... print type(inst) # the exception instance

... print inst.args # arguments stored in .args

... print inst # __str__ allows args to printed directly

... x, y = inst # __getitem__ allows args to be unpacked directly

... print ’x =’, x ... print ’y =’, y ... <type ’instance’> (’spam’, ’eggs’) (’spam’, ’eggs’) x = spam y = eggs

Se uma exceção possui argumento, ele é impresso ao final do detalhamento de expressões não tratadas (unhandled exceptions).

>>> def this_fails():

... x = 1/0

... >>> try:

... this_fails()

... except ZeroDivisionError, detail:

... print ’Handling run-time error:’, detail

...

Handling run-time error: integer division or modulo by zero

8.4

Levantando Exceções

A palavra-reservadaraisepermite ao programador forçar a ocorrência de um determinado tipo de exceção. Por exemplo:

>>> raise NameError, ’HiThere’ Traceback (most recent call last):

File "<stdin>", line 1, in ? NameError: HiThere

O primeiro argumento deraise é o nome da exceção a ser levantada. O segundo argumento, opcional, é o argumento da exceção. O código acima pode ser escrito comoraise NameError(’HiThere). Qualquer forma funciona bem, mas parece haver uma preferência crescente pela última.

Caso você precise determinar se uma exceção foi levantada ou não, mas não quer manipular o erro, uma forma simples deraisepermite que você levante-a novamente.

>>> try:

... raise NameError, ’HiThere’

... except NameError:

... print ’An exception flew by!’

... raise

...

An exception flew by!

Traceback (most recent call last): File "<stdin>", line 2, in ? NameError: HiThere

No documento python24 (páginas 59-62)

Documentos relacionados