Trabalhando com arquivos em Python

Vamos incrementar o nosso programa de contatos que vimos no post sobre dicionários em python para que seja capaz de guardar a lista de contatos. Para isto vamos aprender:

  • Leitura de arquivos em Python
  • Escrita de arquivos em Python
  • Serialização JSON em Python

Ler arquivos em Python

Para trabalhar com arquivos em Python precisamos de uma referência para o arquivo, e obtemos isto utilizando a função open().

f = open(nomedoarquivo, 'r')
f = open("teste.txt", 'r')

O segundo parâmetro indica qual o tipo de operação será feita no arquivo (mode). Veja na tabela abaixo as opções.

ModeExplicação
rAbre o arquivo somente para leitura
r+Abre o arquivo para leitura e escrita, o ponteiro é colocado no início do arquivo
wAbre o arquivo somete para escrita, o ponteiro é colocado no início do arquivo, qualquer informação contida no arquivo é removida e se o arquivo não existir, ele é criado
w+Abre o arquivo para escrita e leitura, o ponteiro é colocado no início do arquivo e qualquer informação contida no arquivo é removida, se o arquivo não existir ele é criado
aAbre o arquivo somente para escrita, o ponteiro é colocado no final do arquivo, por tanto é possível adicionar informações
a+Abre o arquivo para escrita e leitura, o ponteiro é colocado no final do arquivo, por tanto é possível adicionar informações
modos de leitura e escrita em arquivos Python

Escrever arquivos em Python

Toda vez que abrimos um arquivo ficamos com uma referência dele, estamos alocando um recurso do sistema operacional. Por isto tão importante quanto a função open() é a função close(). Que fecha o arquivo e libera o recurso.

Vamos ver como isto funciona na prática. Primeiro vamos escrever em um arquivo e depois ler seu conteúdo:

# escrevendo
f = open('test.txt', 'w')
f.write('texto 1')
f.close()

# lendo
f = open('test.txt', 'r')
print(f.read())
f.close()

Melhor do que sempre lembrar de chamar a função close() é utilizar um mecanismo do Python que cria um contexto que garante que todos os recursos que estão sendo usados no contexto sejam fechados quando ele termina. Para criar este contexto utilizamos a palavra with. Veja como o código fica muito mais limpo, é a maneira mais segura de trabalhar com arquivos em Python:

# escrevendo
with open('test.txt', 'w') as f:
  f.write('texto 1')
  
# lendo
with open('test.txt', 'r') as f:  
  print(f.read())

Utilizaremos agora a opção ‘a’ que nos permite adicionar conteúdo ao arquivo:

# escrita múltipla
with open('test.txt', 'w') as f:
  f.write('texto 1\n')

with open('test.txt', 'a') as f:
  f.write('texto 2\n')

with open('test.txt', 'r') as f:  
  print(f.read()) 
  # texto1
  # texto2

O caractere \n serve para quebrar linha.

Se fizermos a mesma sequencia de operações, porém utilizando a opção ‘w’ na segunda escrita, vamos ver que a palavra “texto 1” vai sumir do arquivo, isto por que a opção ‘w’ limpa o arquivo se ele já existe e coloca o ponteiro no início.

with open('test.txt', 'w') as f:
  f.write('texto 1\n')

with open('test.txt', 'w') as f:
  f.write('texto 2\n')

with open('test.txt', 'r') as f:  
  print(f.read())
  # texto 2

Como salvar arquivo JSON em Python (Serialização)

Imagine que temos um objeto, por exemplo um dicionário e queremos guardá-lo em um arquivo ou transmití-lo por internet. Para fazer isto é preciso transformar este objeto em um formato que possa ser reinterpretado para que o objeto possa ser reconstruído depois.

O processo de serialização é a transformação de um objeto em memória em uma representação de texto ou binária. E o processo de deserialização é o inverso, a partir de um texto ou conteúdo binário é possível montar um objeto.

Processo de serialização e deserialização
Processo de serialização e deserialização

Todas as linguagens de programação possuem bibliotecas de serialização, que permitem transformar o arquivo em diversos formatos como por exemplo binário, texto, xml, json, csv, etc.

JSON é um formato de dados muito utilizado na internet, milhares de serviços na internet se comunicam utilizando JSON e por este motivo vamos aprender a guardar informações em JSON.

Vamos preciar importar o módulo json do Python. Uma das funções dele é a função dump() que recebe o objeto que queremos guardar e uma referência de arquivo onde os dados serão guardados. Vamos criar nossa lista de contato e salvá-la em arquivo no formato JSON:

import json

contatos = {
  "roberta miranda": {
    "nome": "Roberta Miranda",
    "telefone": "79387498374",
    "email": "[email protected]"
  },
  "roberta silva": {
    "nome": "Roberta Silva",
    "telefone": "98273498",
    "email": "[email protected]"
  },
}

with open('contatos.json', 'w') as f:
  json.dump(contatos, f)

Você verá um arquivo com o nome contatos.json com o conteúdo muito similar ao do objeto. Isto ocorre por que a sintaxe do Python para dicionários é muito similar ao formato JSON.

E para ler de um arquivo JSON e transformar em um objeto do Python também e simples, utilizamos a função load().

with open('contatos.json') as f:
      contatos = json.load(contatos, f)

Guardando os contatos em arquivo

Agora que já sabemos ler e escrever em arquivos e utilizar o formato JSON vamos incrementar nosso programa de contatos com a funcionalidade de manter os contatos guardados em disco. Este processo é muito similar à lista de contatos do seu Telefone. Vamos nos basear na versão inicial da lista de contatos que fizemos aqui: https://repl.it/@julianajuliano/Contatos

Para não gerar confusão no nosso código vamos adicionar uma função de carregar_contatos no nosso arquivo de funções:

def carregar_contatos():
  contatos = {}
  if os.path.exists('contatos.json'): 
    with open('contatos.json') as f:
      contatos = json.load(contatos, f)
  return contatos

Precisamos lembrar que a primeira vez que este programa for executado, o arquivo de contatos não vai existir. Por isto fazemos uma verificação utilizando a função exists() do modulo os.path e só tentamos abrir o arquivo caso ele já exista. Como inicializamos a variável contatos com um dicionário vazio podemos retornar ela sem problemas.

O próximo passo é fazer a função que grava os contatos no arquivo. A ideia é receber o dicionário de contatos e salvá-lo no arquivo.

def guardar_contatos(contatos):
  with open('contatos.json', 'w') as f:
    json.dump(contatos, f)

Com essas funções básicas, podemos atualizar nosso programa de contos para carregar os contatos logo no início e salvar toda vez que um novo contato é inserido.

contatos = carregar_contatos()

while comando != "sair": 
  print("                     ")
  comando = input("Digite o comando: (novo, pes, sair):")

  if comando == "novo":
    nome = input("Nome: ").strip()
    telefone = input("Telefone: ").strip()
    email = input("E-mail: ").strip()

    contatos[nome.lower()] = {
      "nome": nome,
      "telefone": telefone,
      "email": email
    }
    guardar_contatos(contatos)

Versão final: https://repl.it/@julianajuliano/Contatos-v2