Python para Desenvolvedores

2ª edição, revisada e ampliada

Capítulo 13: Exceções


Quando ocorre uma falha no programa (como uma divisão por zero, por exemplo) em tempo de execução, uma exceção é gerada. Se a exceção não for tratada, ela será propagada através das chamadas de função até o módulo principal do programa, interrompendo a execução.

In [1]:
print 1/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-1-e19d6e6ac7e1> in <module>()
----> 1 print 1/0

ZeroDivisionError: integer division or modulo by zero

A instrução try permite o tratamento de exceções no Python. Se ocorrer uma exceção em um bloco marcado com try, é possível tratar a exceção através da instrução except. Podem existir vários blocos except para o mesmo bloco try.

In [2]:
try:
    print 1/0
except ZeroDivisionError:
    print 'Erro ao tentar dividir por zero.'
Erro ao tentar dividir por zero.

Se except recebe o nome da exceção, só esta será tratada. Se não for passada nenhuma exceção como parâmetro, todas serão tratadas.

Exemplo:

In [3]:
import traceback

# Tente receber o nome do arquivo
try:
    fn = raw_input('Nome do arquivo: ').strip()

    # Numerando as linhas
    for i, s in enumerate(file(fn)):
        print i + 1, s,

# Se ocorrer um erro
except:

    # Mostre na tela
    trace = traceback.format_exc()

    # E salve num arquivo
    print 'Aconteceu um erro:\n', trace
    file('trace.log', 'a').write(trace)

    # Encerre o programa
    raise SystemExit
An exception has occurred, use %tb to see the full traceback.

SystemExit
Aconteceu um erro:
Traceback (most recent call last):
  File "<ipython-input-3-504455bf1c17>", line 5, in <module>
    fn = raw_input('Nome do arquivo: ').strip()
  File "/usr/local/lib/python2.7/dist-packages/IPython/zmq/ipkernel.py", line 345, in <lambda>
    raw_input = lambda prompt='' : self._no_raw_input()
  File "/usr/local/lib/python2.7/dist-packages/IPython/zmq/ipkernel.py", line 688, in _no_raw_input
    raise StdinNotImplementedError("raw_input was called, but this "
StdinNotImplementedError: raw_input was called, but this frontend does not support stdin.

To exit: use 'exit', 'quit', or Ctrl-D.

O módulo traceback oferece funções para manipular as mensagens de erro. A função format_exc() retorna a saída da última exceção formatada em uma string.

O tratamento de exceções pode possuir um bloco else, que será executado quando não ocorrer nenhuma exceção e um bloco finally, será executado de qualquer forma, tendo ocorrido uma exceção ou não. Novos tipos de exceções podem ser definidos através de herança a partir da classe Exception.

A partir da versão 2.6, está disponível a instrução with, que pode substituir a combinação try / finally em várias situações. Com with, podemos definir um objeto que será usado durante a execução do bloco. O objeto precisa suportar o protocolo de gerenciamento de contexto, o que significa que ele deve possuir um método __enter__(), que é executado no inicio do bloco, e outro chamado __exit__(), que é evocado ao final do bloco.

Exemplo:

In [4]:
import random

# Cria um arquivo com 25 números randômicos
with file('temp.txt', 'w') as temp:
    for y in range(5):
        for x in range(5):
            # "print >> " grava a saída do comando no arquivo indicado
            print >> temp, '%.2f' % random.random(),
        print >> temp

# Exibe o conteúdo do arquivo
with file('temp.txt') as temp:
    for i in temp:
        print i,

# Fora dos blocos, o arquivo está fechado
# Isso gera uma exceção ValueError: I/O operation on closed file
print >> temp
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-ebd2d97619af> in <module>()
     16 # Fora dos blocos, o arquivo está fechado
     17 # Isso gera uma exceção ValueError: I/O operation on closed file
---> 18 print >> temp

ValueError: I/O operation on closed file
0.92 0.67 0.35 0.06 0.12
0.30 0.57 0.29 0.90 0.94
0.51 0.54 0.57 0.58 0.52
0.55 0.00 0.19 0.23 0.50
1.00 0.26 0.66 0.43 0.56

Como o arquivo foi fechado ao final do bloco, a tentativa de gravação gera uma exceção.

In [1]:
 
Out[1]: