Escolar Documentos
Profissional Documentos
Cultura Documentos
UNIDADE 07
Manipulando arquivos
Bom, existem funções para fazer as mesmas operações de leitura e escrita em arquivos.
Para usá-las, precisaremos primeiramente informar um arquivo e abrí-lo. Imagine que
você está trabalhando como um entregador de pizzas: para que você possa entregar a
pizza você precisa, antes de mais nada, saber onde você deverá entregar a pizza, não é?
DICA
Testaremos primeiro alguns exemplos de código e, em seguida,
explicaremos o que este código significa. Por isso, é interessante
que você teste os códigos enquanto vamos os apresentando para
você.
Bom, agora que passamos por estas demonstrações simples é importante entendermos
como usar as funções de leitura e escrita de arquivos. Vamos lá:
1. Função open(): serve para abrir um arquivo. Use-a toda vez que for ler ou escrever
dados em um arquivo.
2. Agora que o arquivo está aberto, você pode ler ou escrever coisas (mais
precisamente, strings).
Escrever coisas:
1. Escrever uma string no arquivo: função write().
2. Esta função não aceita números ou booleanos: você precisará
converter para string.
Ler coisas:
1. Ler uma linha de cada vez: função readline().
2. Ler todo o conteúdo do arquivo em uma só string: função read().
3. Ler todo o conteúdo do arquivo separando linha por linha como
strings em uma única lista: função readlines().
Vamos pensar em mais alguns exemplos para testarmos?
Veja que, como estamos lendo o arquivo, agora o bloco é with open("nome.txt",
"r") as f:. Aquele "r" indica que estamos abrindo o arquivo "nome.txt" no modo de
leitura. O conteúdo do arquivo é lido e armazenado na variável conteudo.
Depois, usamos um for para mostrar cada letra dentro de uma única linha.
primeiro_numero = 1.01
segundo_numero = -2.95
Viu que o bloco começa com with open("nome.txt", "a") as f:? Aquele "a" indica que
somente estamos acrescentando dados no arquivo sem apagar o que já tínhamos
armazenado antes. É esta a diferença principal entre o modo "a" e "w".
Depois, perceba que temos dois write(): eles servem para que armazenemos os dois
números no arquivo. Perceba também duas coisas:
1. Tivemos que converter os números para texto primeiro com o str() (mais
especificamente, com o str(primeiro_numero) e str(segundo_numero)). Isto era
importante porque não somente conseguimos salvar strings no arquivo. Por isso,
precisamos converter os números para strings antes de salvá-los no arquivo.
2. Perceba também que colocamos no início de cada escrita de arquivo um “\n”. Este
caracter significa “line feed”, ou “quebra de linha”. Isto garante com que salvemos cada
número em uma linha separada.
Arquivos JSON
É aí que entram os arquivos JSON. JSON (JavaScript Object Notation) é um formato leve
e de fácil leitura utilizado para a troca de dados entre sistemas. Ele é amplamente
utilizado na comunicação entre aplicativos web e é suportado por várias linguagens de
programação, incluindo o Python.
O JSON é baseado em uma estrutura de dados composta por pares de chave e valor.
Esses pares são organizados em uma sintaxe simples e legível, permitindo representar
informações de forma estruturada. A estrutura básica do JSON consiste em objetos e
arrays (vetores, ou listas).
1. Objetos: são delimitados por chaves {} e consistem em uma coleção não ordenada
de pares chave-valor. Cada chave é uma string única que identifica o valor
associado a ela. Os pares chave-valor são separados por vírgulas.
2. Arrays: são delimitados por colchetes [] e podem conter uma lista ordenada de
valores. Os valores em um array podem ser de qualquer tipo válido do JSON,
incluindo strings, números e outros arrays. Os elementos do array são separados
por vírgulas.
Veja só um exemplo:
{
"nome": "João",
"idade": 25,
"cidade": "Curitiba",
"frutas_favoritas": [
"maçã",
"banana",
"laranja"
]
}
Aqui, todas estas linhas fazem parte de um único objeto JSON. Este objeto possui
quatro chaves (nome, idade, cidade e frutas_favoritas). A chave “nome” armazena uma
string, a chave “idade” armazena um número inteiro, e a chave “cidade” armazena
outra string. Já chave “frutas_favoritas” armazena um array de três valores (percebeu
os colchetes?).
Além disso, o JSON suporta diferentes tipos de dados, como strings, números,
booleanos, valores nulos, listas e matrizes. Agora, para que usamos JSON no mercado
de trabalho? Um dos principais usos é na interoperabilidade entre sistemas (isto é: para
trocar dados entre sistemas escritos em linguagens de programação e empresas
diferentes).
Por ser um formato padrão amplamente adotado no mundo inteiro, ele permite a troca
de dados entre diferentes sistemas e plataformas. É comum utilizar JSON para enviar e
receber dados de APIs (Application Programming Interfaces), permitindo a integração de
sistemas de maneira eficiente.
IMPORTANTE
Percebeu que isso é muito parecido com os dicionários, não é?
Isto não é coincidência.
Vamos para alguns exemplos usando arquivos JSON? Ao contrário da leitura e escrita
de arquivos usando strings em que usávamos write() ou read()/readline()/readlines(),
aqui utilizaremos outras duas funções: dump() e load(). Ambas existem em um módulo
específico do Python para a manipulação de arquivos JSON e que também tem o nome
de json, e elas já realizam todas as conversões de dados que precisamos de forma
automática. Vejamos:
import json
dados = {
"nome": "João",
"idade": 25,
"cidade": "Curitiba",
"frutas_favoritas": [
"maçã",
"banana",
"laranja"
]
}
Ainda que isto funcionasse bem para quem trabalhasse somente com dados
em inglês, ele não é compatível com todos os alfabetos e símbolos especiais
do mundo. Por isso, hoje é normal usarmos outro código mais amplo: o UTF-8
(Unicode). Ele é adequado para aplicações multilíngues e internacionais. Os
emojis fazem também parte do UTF-8.
DICA
um módulo é como uma "biblioteca" de código que pode ser
importada para adicionar funcionalidades extras ao seu
programa. Para utilizar um módulo em seu programa, você
precisa importá-lo. A declaração import nome_do_modulo
permite acessar todas as definições contidas no módulo. Você
pode usar as funções, classes e variáveis do módulo em seu
programa conforme necessário. Por isso, usamos o import json
no começo do nosso arquivo: sem ele, não conseguiríamos ler e
escrever informações em JSON.
Agora, e como leríamos os dados de um arquivo JSON para uma variável? Basta
usarmos a função load(). Vejamos:
import json
print(dados_lidos)
IMPORTANTE
Também é possível usar o json.load()/json.dump() para lermos e
escrevermos listas de dicionários em Python. Será que você não
tem nenhuma atividade que solicitava algo assim?
Videoaula
Que tal nos aprofundarmos na interação dos arquivos JSON? Para isso, assista abaixo a
videoaula sobre manipulação de arquivos e arquivos JSON.
Arquivos e JSON
Arquivos binários
Um arquivo binário é um arquivo cujo conteúdo está em um formato binário: uma série
de bytes sequenciais, normalmente cada um possuindo oito bits de comprimento. O
conteúdo deve ser interpretado por um programa ou um processador de hardware que
entenda antecipadamente a forma exata como esse conteúdo é formatado e como ler
os dados.
Em Python podemos usar o módulo pickle para ler e salvar variáveis sem passar por
nenhum tipo de conversão. Vamos supor que você precise salvar uma variável que
não é um dicionário: logo, você não poderá usar JSON. E, para ajudar, esta variável não
é uma string: logo, usar o que aprendemos com as funções
write()/read()/readline()/readlines() não seria a melhor alternativa. Vejamos o exemplo
abaixo:
import pickle
dados = [1, 2, 3, 4, 5]
O processo é semelhante aos outros exemplos que fizemos até agora. As diferenças são:
DICA
O pickle permite que você armazene e recupere uma ampla
variedade de objetos Python, incluindo listas, tuplas, conjuntos,
classes personalizadas e muito mais. Basta passar o objeto
desejado como argumento para a função pickle.dump(). Use o
pickle quando precisar armazenar e recuperar objetos Python
completos preservando a sua estrutura e tipos de dados.
import pickle
print(variavel_lida)
Novamente: a forma de operarmos o arquivo é muito parecida com o que vimos nos
exemplos anteriores. Algumas mudanças são:
Exceções
----------------------------------------------------------
-----------------
in ()
2 print(numero/0.0)
Erros como os que vimos acima que interrompem a execução de um algoritmo são
chamados de exceções. Veja só: em programação, as exceções são eventos que ocorrem
durante a execução de um programa e podem interromper o fluxo normal das coisas.
Elas representam situações em que algo deu errado, ou em que algo inesperado
aconteceu.
As exceções são como alertas que indicam que algo está errado. Quando uma exceção
ocorre, o programa para e olha ao redor em busca de ajuda para lidar com o problema.
É como se ele dissesse: "Ei, algo deu errado aqui, e não sei como resolver isso. O que eu
devo fazer?".
Tratamento de exceções
Quando essas exceções acontecem é comum que não queremos que o nosso programa
simplesmente trave e pare de funcionar: queremos lidar com essa situação de forma
adequada. A definição de “adequada” depende de cada caso. Pode ser uma mensagem
bonita para o(a) usuário falando que a operação que ele(a) está fazendo é inválida, ou
forçar um valor padrão ou, ainda, direcionar o algoritmo para executar algum outro
pedaço de código. Isto é um tratamento de exceção: uma forma de dizer ao programa
como lidar com a exceção quando ela ocorre.
DICA
Tratamento de exceções é como ter um plano de contingência
para quando algo dá errado.
try:
print(numero/0.0)
except:
print("Não foi possível dividir o número por zero.")
Perceba que modificamos o exemplo inicial da divisão por zero. Colocamos dentro do
try a(s) linha(s) de código que podem dar erro e, dentro do bloco except, o código que
deverá ser executado se o que estiver dentro do try não funcionar.
Se você testar o código acima, verá que aquela exceção que vimos anteriormente
desapareceu: em seu lugar, apareceu uma mensagem mais amigável de erro.
Exemplo de aplicação 10: Mostre um menu simples com opções numéricas ao usuário.
Converta a opção digitada para um número inteiro. Mostre uma mensagem simples de
erro se o valor digitado for inválido (como um texto).
while True:
print("1. Doces")
print("2. Salgados")
print("3. Bebidas")
print("4. Sair")
try:
opcao = int(input("Digite uma opção:"))
except:
print("Você digitou uma opção inválida. Tente
novamente.")
continue
Vamos nos focar no bloco try/except: o código dentro do bloco try está tentando
converter a entrada do usuário em um número inteiro usando a função int(input()). Se
o usuário digitar algo que não possa ser convertido em um número inteiro (como o
texto “chinelo”), uma exceção será gerada.
Se ocorrer uma exceção, o bloco except será executado. Nesse caso, uma mensagem de
erro será exibida informando que uma opção inválida foi digitada, e o loop retornará ao
início graças à palavra-chave continue. Se o continue não existisse, o bloco if/elif/else
seria executado. Como já sabemos que a opção digitada é inválida, estamos forçando o
reinício do loop.
EXERCÍCIO
Exercício de fixação 1: Crie um programa que peça ao usuário
uma 5 números inteiros. Salve estes números dentro de um
arquivo chamado “números.txt”. Cada número deve ocupar uma
linha.
Resolução do exercício
Resolução exercício 1
lista_numeros = []
for i in range(5):
numero = int(input("Digite um número
inteiro: "))
lista_numeros.append(numero)
Resolução do exercício
Resolução exercício 2
soma = 0
with open("números.txt", "r") as arquivo:
for linha in arquivo.readlines():
soma += int(linha)
print(soma)
alunos = [
("João", 18, 9.5),
("Maria", 19, 8.7),
("Pedro", 20, 7.2),
("Ana", 18, 9.0),
("Carlos", 19, 8.5)
]
Resolução do exercício
Resolução exercício 3
alunos = [
("João", 18, 9.5),
("Maria", 19, 8.7),
("Pedro", 20, 7.2),
("Ana", 18, 9.0),
("Carlos", 19, 8.5)
]
Resolução do exercício
Resolução exercício 4
dados = [
{"nome": "João", "idade": 25,
"cidade": "Curitiba"},
{"nome": "Maria", "idade": 30,
"cidade": "São Paulo"},
{"nome": "Carlos", "idade": 28,
"cidade": "Rio de Janeiro"}
]
Resolução do exercício
Resolução exercício 5
import json
dados = [
{"nome": "João", "idade": 25,
"cidade": "Curitiba"},
{"nome": "Maria", "idade": 30,
"cidade": "São Paulo"},
{"nome": "Carlos", "idade": 28,
"cidade": "Rio de Janeiro"}
]
Resolução do exercício
Resolução exercício 6
import json
print(conteudo)
Cadastro de Clientes, Parte II
def menu():
print("\nMenu:")
print("1. Inserir clientes")
print("2. Editar clientes")
print("3. Listar clientes")
print("4. Pesquisar clientes")
print("5. Sair")
def inserir_cliente(clientes):
nome = input("Insira o nome do cliente: ")
clientes.append(nome)
print(f"Cliente {nome} adicionado.")
return clientes
def editar_cliente(clientes):
nome_antigo = input("Insira o nome do cliente a ser
editado: ")
if nome_antigo in clientes:
nome_novo = input("Insira o novo nome do cliente:
")
indice = clientes.index(nome_antigo)
clientes[indice] = nome_novo
print(f"Cliente {nome_antigo} alterado para
{nome_novo}.")
else:
print("Cliente não encontrado.")
return clientes
def listar_clientes(clientes):
print("Lista de clientes:")
for cliente in clientes:
print(cliente)
return None
while True:
menu()
opcao = int(input("Escolha uma opção: "))
if opcao == 1:
clientes = inserir_cliente(clientes)
elif opcao == 2:
clientes = editar_cliente(clientes)
elif opcao == 3:
listar_clientes(clientes)
elif opcao == 4:
nome = input("Insira o nome do cliente a ser
pesquisado: ")
if pesquisar_clientes(clientes, nome):
print(f"Cliente {nome} está na lista.")
else:
print("Cliente não encontrado.")
elif opcao == 5:
print("Saindo do programa...")
break
else:
print("Opção inválida. Tente novamente.")
A primeira coisa que sugiro que façamos é a de implementar duas novas funções: uma
para ler e outra para escrever arquivos JSON. Isto é importante sob um ponto de vista
de testes: criar funções separadas permite que testemos somente a lógica de
manipulação de arquivos JSON sem precisar que nos preocupemos em testar (ou
quebrar) todo o código já existente. Com o que aprendemos até agora, poderíamos ter
duas funções assim:
def escrever_lista_em_json(lista, nome_arquivo):
with open(nome_arquivo, "w") as arquivo:
json.dump(lista, arquivo)
def ler_lista_do_json(nome_arquivo):
try:
with open(nome_arquivo, "r") as arquivo:
lista = json.load(arquivo)
return lista
except:
return []
A primeira função recebe dois parâmetros: a lista que queremos salvar e o nome do
arquivo em que ficará a lista. Já a segunda função recebe como parâmetro de entrada o
nome do arquivo e retorna a lista que está dentro daquele arquivo. Na segunda função
adicionei um try/except simples só para os nossos primeiros testes: se o arquivo ainda
não existir retornaremos uma lista vazia em vez de um erro.
1. inserir_cliente();
2. editar_cliente();
3. listar_clientes();
4. pesquisar_clientes().
Comecemos pela função inserir_cliente(). Hoje, ela está assim:
def inserir_cliente(clientes):
nome = input("Insira o nome do cliente: ")
clientes.append(nome)
print(f"Cliente {nome} adicionado.")
return clientes
Como queremos tirar a dependência direta daquela lista “clientes” e passar a consumir
do arquivo JSON diretamente, faremos as seguintes alterações:
def inserir_cliente(nome_arquivo):
clientes = ler_lista_do_json(nome_arquivo)
nome = input("Insira o nome do cliente: ")
clientes.append(nome)
print(f"Cliente {nome} adicionado.")
escrever_lista_em_json(clientes, nome_arquivo)
return None
Sugiro que você teste esta função antes de mais nada. Se fizermos diretamente no
código um inserir_cliente("teste2.json") é provável que a sua função funcione
corretamente, e que o seu cliente seja salvo dentro do arquivo teste2.json.
DICA
Sempre teste uma mudança de cada vez. Assim, você conseguirá
reverter as alterações e entender facilmente qualquer erro no seu
código.
A mesma lógica pode ser aplicada às funções de editar, listar e pesquisar clientes. Hoje,
elas estão assim:
def editar_cliente(clientes):
nome_antigo = input("Insira o nome do cliente a ser
editado: ")
if nome_antigo in clientes:
nome_novo = input("Insira o novo nome do cliente:
")
indice = clientes.index(nome_antigo)
clientes[indice] = nome_novo
print(f"Cliente {nome_antigo} alterado para
{nome_novo}.")
else:
print("Cliente não encontrado.")
return clientes
def listar_clientes(clientes):
print("Lista de clientes:")
for cliente in clientes:
print(cliente)
return None
Com as nossas mudanças para ler e escrever no arquivo JSON seguindo a mesma lógica
anterior, ficaria assim (alterações em negrito e itálico):
def editar_cliente(nome_arquivo):
clientes = ler_lista_do_json(nome_arquivo)
nome_antigo = input("Insira o nome do cliente a ser
editado: ")
if nome_antigo in clientes:
nome_novo = input("Insira o novo nome do cliente:
")
indice = clientes.index(nome_antigo)
clientes[indice] = nome_novo
print(f"Cliente {nome_antigo} alterado para
{nome_novo}.")
else:
print("Cliente não encontrado.")
escrever_lista_em_json(clientes, nome_arquivo)
return None
def listar_clientes(nome_arquivo):
clientes = ler_lista_do_json(nome_arquivo)
print("Lista de clientes:")
for cliente in clientes:
print(cliente)
return None
Perceba que sempre começamos as funções lendo o conteúdo do arquivo: isto serve
para que sempre possamos pegar a versão mais atualizada do arquivo JSON. Também
veja que somente escrevemos (atualizamos) o arquivo JSON na função editar_cliente():
afinal, não atualizamos nenhum dado dentro das funções de listar e pesquisar clientes.
Portanto, não seria necessário escrever novamente a lista no arquivo JSON uma vez que
não houve alterações.
Agora, vamos alterar o bloco principal do código. Atualmente, ele está assim:
clientes = []
while True:
menu()
opcao = int(input("Escolha uma opção: "))
if opcao == 1:
clientes = inserir_cliente(clientes)
elif opcao == 2:
clientes = editar_cliente(clientes)
elif opcao == 3:
listar_clientes(clientes)
elif opcao == 4:
nome = input("Insira o nome do cliente a ser
pesquisado: ")
if pesquisar_clientes(clientes, nome):
print(f"Cliente {nome} está na lista.")
else:
print("Cliente não encontrado.")
elif opcao == 5:
print("Saindo do programa...")
break
else:
print("Opção inválida. Tente novamente.")
arquivo = 'clientes.json'
while True:
menu()
try:
opcao = int(input("Escolha uma opção: "))
except:
print("Apenas números são permitidos. Tente
novamente.")
continue
if opcao == 1:
inserir_cliente(arquivo)
elif opcao == 2:
editar_cliente(arquivo)
elif opcao == 3:
listar_clientes(arquivo)
elif opcao == 4:
nome = input("Insira o nome do cliente a ser
pesquisado: ")
if pesquisar_clientes(arquivo, nome):
print(f"Cliente {nome} está na lista.")
else:
print("Cliente não encontrado.")
elif opcao == 5:
print("Saindo do programa...")
break
else:
print("Opção inválida. Tente novamente.")
O código final (quer dizer, uma das implementações possíveis) ficará assim:
def ler_lista_do_json(nome_arquivo):
try:
with open(nome_arquivo, "r") as arquivo:
lista = json.load(arquivo)
return lista
except:
return []
def menu():
print("\nMenu:")
print("1. Inserir clientes")
print("2. Editar clientes")
print("3. Listar clientes")
print("4. Pesquisar clientes")
print("5. Sair")
def inserir_cliente(nome_arquivo):
clientes = ler_lista_do_json(nome_arquivo)
nome = input("Insira o nome do cliente: ")
clientes.append(nome)
print(f"Cliente {nome} adicionado.")
escrever_lista_em_json(clientes, nome_arquivo)
return None
def editar_cliente(nome_arquivo):
clientes = ler_lista_do_json(nome_arquivo)
nome_antigo = input("Insira o nome do cliente a ser
editado: ")
if nome_antigo in clientes:
nome_novo = input("Insira o novo nome do cliente:
")
indice = clientes.index(nome_antigo)
clientes[indice] = nome_novo
print(f"Cliente {nome_antigo} alterado para
{nome_novo}.")
else:
print("Cliente não encontrado.")
escrever_lista_em_json(clientes, nome_arquivo)
return None
def listar_clientes(nome_arquivo):
clientes = ler_lista_do_json(nome_arquivo)
print("Lista de clientes:")
for cliente in clientes:
print(cliente)
return None
arquivo = 'clientes.json'
while True:
menu()
try:
opcao = int(input("Escolha uma opção: "))
except:
print("Apenas números são permitidos. Tente
novamente.")
continue
if opcao == 1:
inserir_cliente(arquivo)
elif opcao == 2:
editar_cliente(arquivo)
elif opcao == 3:
listar_clientes(arquivo)
elif opcao == 4:
nome = input("Insira o nome do cliente a ser
pesquisado: ")
if pesquisar_clientes(arquivo, nome):
print(f"Cliente {nome} está na lista.")
else:
print("Cliente não encontrado.")
elif opcao == 5:
print("Saindo do programa...")
break
else:
print("Opção inválida. Tente novamente.")
Referências Bibliográficas