e sistemas de banco de dados para importação e exportação de informações. 60 Exceções 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. print 1/0 Traceback (most recent call last): File "<input>", line 1, in ? 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 excepts para um try. try: print 1/0 except ZeroDivisionError: print 'Erro ao tentar dividir por zero.' # Mostra: # 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. 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() Exceções 61 # E salve num arquivo print 'Aconteceu um erro:\n', trace file('trace.log', 'a').write(trace) # Encerre o programa raise SystemExit 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ão15. Novos tipos de exceções podem ser definidos através de herança a partir da classe Exception. 15 A declaração finally pode ser usada para liberar recursos que foram usados no bloco try, tais como conexões de banco de dados ou arquivos abertos. 62 Tempo Tempo O Python possui dois módulos para lidar com tempo: ▪ time: implementa funções básicas para lidar com o tempo gerado pelo sistema operacional. ▪ datetime: implementa tipos de alto nível para lidar operações de data e hora. Exemplo com time: # -*- coding: latin-1 -*- import time # localtime() Retorna a data e hora local no formato # de uma tupla: # (ano, mês, dia, hora, minuto, segundo, dia da semana, # dia do ano, horário de verão) print time.localtime() # asctime() retorna a data e hora como string, conforme # a configuração do sistema operacional print time.asctime() # time() retorna o tempo do sistema em segundos ts1 = time.time() # gmtime() converte segundos para tuplas no mesmo # formato de localtime() tt1 = time.gmtime(ts1) print ts1, '=>', tt1 # Somando uma hora tt2 = time.gmtime(ts1 + 3600.) # mktime() converte tuplas para segundos ts2 = time.mktime(tt2) print ts2, '=>', tt2 # clock() retorma o tempo desde quando o programa # iniciou, em segundos print 'O programa levou', time.clock(), \ 'segundos sendo executado até agora...' # Contando os segundos... for i in xrange(5): # sleep() espera durante o número de segundos # especificados time.sleep(1) Tempo 63 print i + 1, 'segundo(s)' Saída: (2008, 5, 11, 9, 55, 57, 6, 132, 0) Sun May 11 09:55:57 2008 1210510557.44 => (2008, 5, 11, 12, 55, 57, 6, 132, 0) 1210524957.0 => (2008, 5, 11, 13, 55, 57, 6, 132, 0) O programa levou 1.53650813162e-006 segundos sendo executado até agora... 1 segundo(s) 2 segundo(s) 3 segundo(s) 4 segundo(s) 5 segundo(s) Em datetime, estão definidos quatro tipos para representar o tempo: ▪ datetime: data e hora. ▪ date: apenas data. ▪ time: apenas hora. ▪ timedelta: diferença entre tempos. Exemplo: # -*- coding: latin-1 -*- import datetime # datetime() recebe como parâmetros: # ano, mês, dia, hora, minuto, segundo # e retorna um objeto do tipo datetime dt = datetime.datetime(2020, 12, 31, 23, 59, 59) # Objetos date e time podem ser criados # a partir de um objeto datetime data = dt.date() hora = dt.time() # Quanto tempo falta para 31/12/2020 dd = dt - dt.today() print 'Data:', data print 'Hora:', hora print 'Quanto tempo falta para 31/12/2020:', \ str(dd).replace('days', 'dias') Saída: 64 Tempo Data: 2020-12-31 Hora: 23:59:59 Quanto tempo falta para 31/12/2020: 4616 dias, 13:22:58.857000 Os objetos dos tipos date e datetime retornam datas em formato ISO. Introspecção 65 Introspecção Introspecção ou reflexão é capacidade do software de identificar e relatar suas próprias estruturas internas, tais como tipos, escopo de variáveis, métodos e atributos. Funções nativas do interpretador para introspecção: Função Retorno type(objeto) O tipo (classe) do objeto. id(objeto) O identificador do objeto. locals() O dicionário de variáveis locais. globals() O dicionário de variáveis globais. len(objeto) O tamanho do objeto. dir(objeto) A lista de estruturas do objeto. help(objeto) As Doc Strings do objeto. repr(objeto) A representação do objeto. isinstance(objeto, classe) Verdadeiro se objeto deriva da classe. issubclass(subclasse, classe) Verdadeiro se subclasse herda classe. O identificador do objeto é um número inteiro único que é usado pelo interpretador para identificar internamente os objetos. Exemplo: # -*- coding: latin1 -*- # Colhendo algumas informações # dos objetos globais no programa from types import ModuleType def info(n_obj): # Cria uma referência ao objeto obj = globals()[n_obj] # Mostra informações sobre o objeto print 'Nome do objeto:', n_obj print 'Identificador:', id(obj) print 'Tipo:', type(obj) print 'Representação:', repr(obj) 66 Introspecção # Se for um módulo if isinstance(obj, ModuleType): print 'itens:' for item in dir(obj): print item print # Mostrando as informações for n_obj in dir(): info(n_obj) O Python também tem um módulo chamado types, que tem as definições dos tipos básicos do interpretador. Através da introspecção, é possível determinar os campos de uma tabela de banco de dados, por exemplo. Módulo inspect O módulo inspect provê um conjunto de funções de introspecção prontas que permitem investigar tipos , itens de coleções, classes, funções, código fonte e a pilha de execução do interpretador. Exemplo: # -*- coding: latin1 -*- import os.path # inspect: módulo de introspecção "amigável" import inspect print 'Objeto:', inspect.getmodule(os.path) print 'Classe?', inspect.isclass(str) # Lista todas as funções que existem em "os.path" print 'Membros:', for name, struct in inspect.getmembers(os.path): if inspect.isfunction(struct): print name, Saída: Introspecção 67 Objeto: <module 'ntpath' from 'C:\Python24\lib\ntpath.pyc'> Classe? True Membros: abspath basename commonprefix dirname exists expanduser expandvars getatime getctime getmtime getsize isabs isdir isfile islink ismount join lexists normcase normpath realpath split splitdrive splitext splitunc walk As funções que trabalham com a pilha do interpretador devem ser usadas com cuidado, pois é possível criar referências cíclicas (uma variável que aponta para o item da pilha que tem a própria variável). A existência de referências a itens da pilha retarda a destruição dos itens pelo coletor de lixo do interpretador. 68 Exercícios II Exercícios II 1. Implementar um programa que receba um nome de arquivo e gere estatísticas sobre o arquivo (número de caracteres, número de linhas e número de palavras) 2. Implementar um módulo com duas funções: