Input e Output

Prévio Próximo

Python Logo7. Input e Output

Existem várias maneiras de apresentar a saída de um programa; os dados podem ser impressos em forma legível, ou escritos em um arquivo para uso futuro. Este capítulo irá discutir algumas das possibilidades.

7.1. Formatação de Saída Mais Extravagante

Até agora nós encontramos duas maneiras de escrever valores: comandos de expressão e pelo comando print. (A terceira maneira é utilizando o método write() de objetos de arquivo, o arquivo de saída padrão pode ser referenciado como sys.stdout Veja a Biblioteca de Referência para obter mais informações sobre este assunto..)
Muitas vezes você vai querer mais controle sobre a formatação de sua saída do que simplesmente imprimindo valores separados por espaços. Há duas maneiras de formatar a sua saída; A primeira maneira é fazer toda a manipulação de string voce mesmo; usando operações de corte e concatenação de strings você pode criar qualquer layout que você possa imaginar. Os tipos de string têm alguns métodos que executam operações úteis para modificar strings para uma determinada largura de coluna fornecida; estas serão discutidas em breve. A segunda maneira consiste em usar o método str.format ().

O módulo string contém uma classe de modelo que oferece mais uma forma de substituir valores em strings.

Uma pergunta permanece, é claro: como você converter valores para strings? Felizmente, Python tem maneiras de converter qualquer valor para uma string: passá-lo para as funções repr() ou str().

A função str() destina-se a retornar representações de valores que são bastante legível, enquanto repr() destina-se a gerar as representações que podem ser lidos pelo interpretador (ou forçarão um SintaxError se não houver sintaxe equivalente). Para objetos que não têm uma representação específica para o consumo humano, str() irá retornar o mesmo valor que repr(). Muitos valores, tais como números ou estruturas como listas e dicionários, têm a mesma representação usando qualquer uma daquelas funções. Strings e números de ponto flutuante, em particular, têm duas representações distintas.
Alguns exemplos:
>>> s = 'Hello, world.'
>>> str(s)
'Hello, world.'
>>> repr(s)
"'Hello, world.'"
>>> str(1.0/7.0)
'0.142857142857'
>>> repr(1.0/7.0)
'0.14285714285714285'
>>> x = 10 * 3.25
>>> y = 200 * 200
>>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
>>> print s
The value of x is 32.5, and y is 40000...
>>> # The repr() of a string adds string quotes and backslashes:
... hello = 'hello, world\n'
>>> hellos = repr(hello)
>>> print hellos'hello, world\n'
>>> # The argument to repr() may be any Python object:
... repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"
Aqui estão duas maneiras de escrever uma tabela de quadrados e cubos:
>>> for x in range(1, 11):
...     print repr(x).rjust(2), repr(x*x).rjust(3),
...     # Note trailing comma on previous line
...     print repr(x*x*x).rjust(4)
... 
1   1    1
2   4    8 
3   9   27 
4  16   64 
5  25  125 
6  36  216 
7  49  343 
8  64  512 
9  81  729
10 100 1000
>>> for x in range(1,11):
...     print '{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x)
... 
1   1    1
2   4    8 
3   9   27 
4  16   64 
5  25  125 
6  36  216 
7  49  343 
8  64  512 
9  81  729
10 100 1000

(Note-se que no primeiro exemplo, um espaço entre cada coluna foi adicionado pelo geito que print trabalha: sempre adiciona espaços entre seus argumentos)

Este exemplo demonstra o método str.rjust() de objetos string, que justifica à direita uma string em um campo de uma dada largura por preenchimento com espaços à esquerda. Existem métodos semelhantes str.ljust() e str.center(). Estes métodos não escrevem nada, eles só retornam uma nova string. Se a input de entrada é muito longa, eles não a truncam, mas devolvem-na inalterada; isso vai atrapalhar sua coluna de lay-out, mas que é geralmente melhor do que a alternativa, que seria mentir sobre um valor. (Se você realmente quer truncamento você pode sempre adicionar uma operação de slice, como em x.ljust(n)[n].)

Há um outro método, str.zfill(), que preenche uma string numérica na esquerda com zeros. Ele entende sobre sinais positivos e negativos:

>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'
Uso básico do método str.format () se parece com isso:
>>> print 'We are the {} who say "{}!"'.format('knights', 'Ni')
We are the knights who say "Ni!"
Os brackets e caracteres dentro deles (chamados campos de formato) são substituídos por objetos que são passados para o método str.format(). Um número entre parênteses refere-se à posição do objecto transmitido para o método str.format
>>> print '{0} and {1}'.format('spam', 'eggs')
spam and eggs
>>> print '{1} and {0}'.format('spam', 'eggs')
eggs and spam
Se argumentos keyword forem utilizados no método str.format(), os seus valores são referidos usando o nome do argumento.
>>> print 'This {food} is {adjective}.'.format(
...       food='spam', adjective='absolutely horrible')
This spam is absolutely horrible.
Argumentos posicionais e keyword e podem ser arbitrariamente combinados:
>>> print 'The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred',
...                                                    other='Georg')
The story of Bill, Manfred, and Georg.
‘! s‘ (apply str()) e ‘! r‘ (apply repr()) pode ser usado para converter o valor antes de ser formatado.
>>> import math
>>> print 'The value of PI is approximately {}.'.format(math.pi)
The value of PI is approximately 3.14159265359.
>>> print 'The value of PI is approximately {!r}.'.format(math.pi)
The value of PI is approximately 3.141592653589793.
Um ‘:’ opcional e um especificador de formato podem seguir o nome do campo. Isto permite um maior controle sobre a forma como o valor é formatado. O exemplo a seguir arredonda Pi três casas depois da vírgula.
>>> import math
>>> print 'The value of PI is approximately {0:.3f}.'.format(math.pi)
The value of PI is approximately 3.142.
Passando um inteiro após o ‘:’ fará com que o campo seja um número mínimo de caracteres de largura. Isto é útil para fazer tabelas bonita.
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
...     print '{0:10} ==> {1:10d}'.format(name, phone)
...
Jack       ==>       4098
Dcab       ==>       7678
Sjoerd     ==>       4127
Se você tiver uma string de formato realmente muito longo que você não quer dividir, seria bom se você pudesse referenciar as variáveis a serem formatadas pelo nome, em vez de por posição. Isso pode ser feito simplesmente passando o dict e usando colchetes ‘[]’ para acessar as chaves
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print ('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
...        'Dcab: {0[Dcab]:d}'.format(table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678
Isso também poderia ser feito passando a table como  argumento keyword com a notação “**“.
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print 'Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table)
Jack: 4098; Sjoerd: 4127; Dcab: 8637678

Isso é particularmente útil em combinação com a função interna vars(), que retorna um dicionário contendo todas as variáveis locais.

Para uma visão completa de formatação de string com str.format(), consulte Formato de Sintaxe de String.

7.1.1. Formatação de Strings Velha

O operador % também pode ser usado para a formatação de strings. Ele interpreta o argumento esquerdo muito parecido com um estilo sprintf() de formatação de string a ser aplicado ao argumento da direita, e retorna a string resultante desta operação de formatação. Por exemplo:
>>> import math
>>> print 'The value of PI is approximately %5.3f.' % math.pi
The value of PI is approximately 3.142.
Mais informações podem ser encontradas na seção de Operações formatação de cadeia.

7.2. Lendo e Escrevendo em Arquivos

A funçã open() retorna um objeto de arquivo, e é mais comumente usada com dois argumentos: open(nomedoarquivo, modo).
>>> f = open('workfile', 'w')
>>> print f
<open file 'workfile', mode 'w' at 80a0960>
O primeiro argumento é uma string contendo o nome do arquivo. O segundo argumento é outra string contendo alguns caracteres que descrevem a forma na qual o arquivo será usado. modo pode ser ‘r‘ quando o arquivo será só de leitura, ‘w‘ para apenas escrever (um arquivo existente com o mesmo nome será apagado), e ‘a‘ abre o arquivo para acrescentar (append); todos os dados gravados no arquivo são automaticamente adicionados ao final. ‘r +‘ abre o arquivo para leitura e escrita. O argumento modo é opcional; ‘r‘ será assumido se for omitido.
No Windows, ‘b‘ anexado ao modo abre o arquivo em modo binário, por isso existem os modos como ‘rb‘, ‘bu‘, e ‘r + b‘. Python no Windows faz uma distinção entre texto e arquivos binários; os caracteres de fim de linha em arquivos de texto são automaticamente alterados ligeiramente quando os dados são lidos ou escritos. Esta modificação “por tras da cena” em arquivo de dados é bom para arquivos de texto ASCII, mas corromperá dados binários em arquivos JPEG ou EXE. Tenha muito cuidado ao usar o modo binário para ler e gravar esses arquivos. No Unix, não faz mal acrescentar um ‘b’ para o modo, para que você possa usá-lo de forma independente de plataforma para todos os arquivos binários.

7.2.1. Métodos dos Objetos Tipo Arquivo

O resto dos exemplos desta seção irá assumir que um objeto arquivo chamado f já foi criado.
Para ler o conteúdo do arquivo, chame f.read(tamanho), que lê alguma quantidade de dados e retorna como uma string. Tamanho é um argumento numérico opcional. Quando tamanho é omitido ou negativo, todo o conteúdo do arquivo será lido e retornado; o problema é seu, se o arquivo é duas vezes maior que a memória de sua máquina. Caso contrário, a maioria dos bytes até o tamanho são lidos e devolvidos. Se o fim do arquivo foi alcançado, f.read() irá retornar uma string vazia (“”).
>>> f.read()
'This is the entire file.\n'
>>> f.read()
''
f.readline() lê uma única linha do arquivo; um caractere de nova linha (\ n) é deixado no final da cadeia, e só é omitido na última linha do arquivo se o arquivo não termina em uma nova linha. Isso faz o valor de retorno não ambíguo; se f.readline() retornar uma string vazia, o fim do arquivo foi alcançado, enquanto uma linha em branco é representada por ‘\ n’, uma string que contém apenas uma única nova linha.
>>> f.readline()
'This is the first line of the file.\n'
>>> f.readline()
'Second line of the file\n'
>>> f.readline()
''
Para ler as linhas de um arquivo, você pode fazer um loop sobre o objeto arquivo. Esta é eficiente para a memória, rápido, e leva a um código simples:
>>> for line in f:
        print line,

This is the first line of the file.
Second line of the file
Se você quiser ler todas as linhas de um arquivo em uma lista que você também pode usar list(f) ou f.readlines().
f.write(string) escreve o conteúdo da string no arquivo, retornando None.
>>> f.write('This is a test\n')
Para escrever algo diferente de uma string, precisa ser convertido para uma string em primeiro lugar:
>>> value = ('the answer', 42)
>>> s = str(value)
>>> f.write(s)
f.tell() retorna um inteiro dando a posição atual do objeto de arquivo no arquivo, medida em bytes a partir do início do arquivo. Para alterar a posição do objeto de arquivo, use f.seek(offset, de_onde). A posição é calculada pela soma do offset a um ponto de referência; o ponto de referência é selecionado pelo argumento de_onde. Um de_onde com valor de 0 medidas a partir do início do arquivo, 1 usa a posição do arquivo corrente e 2 usa o final do arquivo como ponto de referência. O argumento de_onde pode ser omitido e será 0, com o início do arquivo como ponto de referência.
>>> f = open('workfile', 'r+')
>>> f.write('0123456789abcdef')
>>> f.seek(5)     # Go to the 6th byte in the file
>>> f.read(1)
'5'
>>> f.seek(-3, 2) # Go to the 3rd byte before the end
>>> f.read(1)
'd'
Quando você terminar com um arquivo, chame f.close() para fechá-lo e liberar quaisquer recursos do sistema tomados pelo arquivo aberto. Depois de chamar f.close(), as tentativas de usar o objeto de arquivo falharão automaticamente.
>>> f.close()
>>> f.read()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: I/O operation on closed file
É uma boa prática para usar a palavra-chave with quando se lida com objetos de arquivo. Isto tem a vantagem de que o arquivo estará bem fechado após seu uso, mesmo que uma exceção seja gerada no caminho. Também é muito mais curto do que escrever blocos equivalentes a try-finally:
>>> with open('workfile', 'r') as f:
...     read_data = f.read()
>>> f.closed
True
Objetos de arquivo têm alguns métodos adicionais, como isatty() e truncate(), que são usados com menos frequência; consultar a Biblioteca de Referência para um guia completo para objetos de arquivo.

7.2.2. Salvando Dados Estruturados com json

Strings podem ser facilmente gravadas e lidas de um arquivo. Números exigem um pouco mais de esforço, uma vez que o método read() retorna apenas strings, que terão de ser passado para uma função como int(), que recebe uma string como ‘123’ e retorna seu valor numérico 123. Quando você quiser salvar tipos de dados mais complexos, como listas aninhadas e dicionários, análise e serialização à mão torna-se complicado.

Ao invés de ter os usuários constantemente escrevendo e depurando código para salvar os tipos de dados complexos para arquivos, Python permite que você use o formato de intercâmbio de dados popular chamado JSON (JavaScript Object Notation). O módulo padrão chamado JSON pode ter hierarquias de dados Python, e convertê-los em representações de string; este processo é chamado de serialização. Reconstruir os dados da representação da stgring é chamado desserialização. Entre serialização e desserialização, a string que representa o objeto pode ter sido armazenada em um arquivo ou dados, ou enviados através de uma conexão de rede para alguma máquina distante.

Nota O formato JSON é comumente usado por aplicativos modernos para permitir a troca de dados. Muitos programadores já estão familiarizados com ele, o que o torna uma boa escolha para a interoperabilidade.
Se você tem um objeto x, você pode ver a sua representação em cadeia JSON com uma simples linha de código:
>>> json.dumps([1, 'simple', 'list'])
'[1, "simple", "list"]'
Outra variante da função dumps(), chamado de dump(), simplesmente serializa o objeto para um arquivo. Então, se f é um objeto de arquivo aberto para escrita, podemos fazer isso:
json.dump(x, f)
Para decodificar o objeto novamente, se f é um objeto de arquivo que foi aberto para leitura:
x = json.load(f)
Esta técnica de serialização simples pode lidar com listas e dicionários, mas serializar instâncias de classe arbitrárias em JSON requer um pouco de esforço extra. A referência para o Módulo json contém uma explicação sobre isso.

Veja tambem

pickle – o módulo pickle

Ao contrário do JSON, pickle é um protocolo que permite a serialização de objetos Python arbitrariamente complexas. Como tal, ele é específico para Python e não pode ser usado para se comunicar com aplicações escritas em outras línguas. Ele também é inseguro por padrão: deserializing dados provenientes de pickle de uma fonte não confiável pode executar código arbitrário, se os dados foram feitos por um atacante habilidoso.
Prévio Próximo