domingo, 25 de outubro de 2015

Python para Testers 11 – Manipulando arquivos

A ideia deste post é exemplificar como é que se trabalha com arquivos em Python. Trabalhar com arquivos é muito parecido com trabalhar com livros. Para utilizar um livro, você tem que abri-lo. Quando você termina, você tem que fechá-lo. Enquanto o livro estiver aberto, você pode tanto lê-lo quanto escrever nele. Em qualquer caso, você sabe onde você está situado no livro. Na maioria das vezes, você lê o livro inteiro em sua ordem natural, mas você também pode saltar através de alguns trechos.

Abrindo arquivo:
Ao abrir um arquivo é criado um objeto do tipo arquivo, Neste exemplo, a variável f se referencia ao novo objeto arquivo.
>>> f = open("teste.dat", "w")
>>> print f

A função open recebe dois argumentos. O primeiro é o nome do arquivo, e o segundo é o modo. Modo " w" Significa que estamos abrindo o arquivo para gravação ("write", escrever).
Se não existir nenhum arquivo de nome teste.dat, ele será criado. Se já existir um, ele será substituído pelo arquivo que estamos gravando (ou escrevendo).

Escrevendo no arquivo
Para escrever no arquivo usamos o método write:
>>> f.write("Agora é hora")
>>> f.write("de fechar o arquivo")

Fechando o arquivo:
Fechar o arquivo diz ao sistema que terminamos de escrever (gravar) e que o arquivo está livre para ser lido:
>>> f.close()

Lendo do arquivo:
Podemos abrir o arquivo de novo, desta vez para leitura, e ler o seu conteúdo para uma string.  Desta vez, o argumento modo é "r" para leitura ("reading"):

>>> f = open("teste.dat", "r")

Caso o arquivo não exista será retornado um erro:
>>> f = open("teste.cat", "r")
IOError: [Errno 2] No such file or directory: 'teste.cat'

O método read lê dados do arquivo. Sem argumentos, ele lê todo o conteúdo do arquivo:
>>> texto = f.read()
>>> print texto
Agora é horade fechar o arquivo
* Não existe espaço entre 'hora' e 'de' porque nós não gravamos um espaço entre as strings.


O read também pode receber um argumento que indica quantos caracteres ler:
>>> f = open("teste.dat", "r")
>>> print f.read(9)
Agora é h

Arquivo de Texto:
Arquivos textos são os famosos “.txt”. Um arquivo texto é um arquivo que contém caracteres imprimíveis e espaços, organizados dentro de linhas separadas por caracteres de nova linha. Já que Pyhton é especialmente projetado para processar arquivos texto, ele oferece métodos que tornam esta tarefa mais fácil.

 Para demonstrar, vamos criar um arquivo texto com três linhas de texto separadas por caracteres de nova linha:
>>> f = open("teste.dat", "w")
>>> f.write("linha um\nlinha dois\nlinha três\n")
>>> f.close()

O comando readlines retorna todas as linhas restantes como uma lista de strings:
>>> print f.readlines()
['linha dois\012', 'linha três\012']

Neste caso, a saída está em formado de lista, o que significa que as strings aparecem entre aspas e o caractere de nova linha aparece como a seqüência de escape 012.

No fim do arquivo, readline retorna a string vazia e readlines retorna a lista vazia:·.
A seguir temos um exemplo de um programa de processamento de linhas. filtraArquivo faz uma cópia de velhoArquivo, omitindo quaisquer linhas que comecem por #:

def filtraArquivo(velhoArquivo, novoArquivo):
  f1 = open(velhoArquivo, "r")
  f2 = open(novoArquivo, "w")
  while 1:
      texto = f1.readline()
      if texto == "":
          break
      if texto[0] == '#':
          continue
      f2.write(texto)
  f1.close()
  f2.close()
  return

O comando continue termina a iteração corrente do loop, mas continua iterando o loop. O fluxo de execução passa para o topo do loop, checa a condição e prossegue conforme o caso.
Assim, se texto for a string vazia, o loop termina. Se o primeiro caractere de texto for o jogo da velha (? # ?), o fluxo de execução passa para o topo do loop. Somente se ambas as condições falharem é que texto será copiado para dentro do novo arquivo.

Gravando Variáveis no arquivo:
O argumento de write tem que ser uma string, assim se quisermos colocar outros valores em um arquivo, temos de convertê-los para strings primeiro. A maneira mais fácil de fazer isso é com a função str:
>>> x = 52
>>> f.write(str(x))

Lendo arquivos dentro de pastas:
Quando você cria um novo arquivo abrindo-o e escrevendo nele, o novo arquivo fica no diretório corrente (seja lá onde for que você esteja quando rodar o programa). Do mesmo modo, quando você abre um arquivo para leitura, Python procura por ele no diretório corrente.
Se você quiser abrir um arquivo que esteja em algum outro lugar, você tem que especificar o caminho (path) para o arquivo, o qual é o nome do diretório (ou folder) onde o arquivo está localizado:

>>> f = open("/usr/share/dict/words", "r")
>>> print f.readline()
Aarhus

Este exemplo abre um arquivo chamado words que reside em um diretório de nome dict, o qual reside em share, o qual reside em usr, o qual reside no diretório de mais alto nível do sistema, chamado /.

Você não pode usar / como parte do nome de um arquivo; ela é um caractere reservado como um delimitador entre nomes de diretórios e nomes de arquivos.
O arquivo /usr/share/dict/words contém uma lista de palavras em ordem alfabética, na qual a primeira palavra é o nome de uma universidade Dinamarquesa.

Tratando Exceções de abertura de arquivo
Às vezes queremos executar uma operação que pode causar uma exceção, mas não queremos que o programa pare. Nós podemos tratar a exceção usando as instruções try e except.

Por exemplo, podemos pedir ao usuário um nome de arquivo e então tentar abri-lo. Se o arquivo não existe, não queremos que o programa trave; queremos tratar a exceção:
nomedoarquivo = raw_input(?Entre com o nome do arquivo: ?)
try:
  f = open (nomedoarquivo, ?r?)
except:
  print ?Não existe arquivo chamado?, nomedoarquivo

A instrução try executa os comandos do primeiro bloco. Se não ocorrerem exceções, ele ignora a instrução except. Se qualquer exceção acontece, ele executa os comandos do ramo except e continua.
Podemos encapsular esta habilidade numa função: existe toma um nome de arquivo e retorna verdadeiro se o arquivo existe e falso se não existe:

def entraNumero():
  x = input (?Escolha um número: ?)
  if x == 17:
    raise ?ErroNumeroRuim?, ?17 é um número ruim?
  return x

O comando raise toma dois argumentos: o tipo da exceção e informações específicas sobre o erro. ErroNumeroRuim é um novo tipo de exceção que nós inventamos para esta aplicação.
Se a função que chamou entraNumero trata o erro, então o programa pode continuar; de outro modo, Pyhton exibe uma mensagem de erro e sai:


>>> entraNumero()
Escolha um número: 17
ErroNumeroRuim: 17 é um número ruim

A mensagem de erro inclui o tipo da exceção e a informação adicional que você forneceu.
Como um exercício, escreva uma função que use entraNumero para pegar um número do teclado e que trate a exceção ErroNumeroRuim.

Hora do Treino:
- Copie o conteúdo de um arquivo, lendo e gravando em outro arquivo,  até cinqüenta caracteres de uma vez.

Bibliografia:
Aprenda Computação com Python. Disponível em: http://www3.ifrn.edu.br/~jurandy/fdp/doc/aprenda-python/index.html