• Python
  • 11. Arquivos
  • Handout

10. Arquivos#

Info

Os testes deste handout utilizam arquivos externos. Por esse motivo, a melhor maneira de entender o que o programa está fazendo é executá-lo no próprio computador para observar as mudanças nos outros arquivos.

Nossos programas até o momento utilizam dados fornecidos pelo usuário ou obtidos a partir de algum cálculo, mas esses dados são perdidos assim que o programa acaba. Arquivos são estruturas de dados que normalmente são armazenados em dispositivos secundários de memória. Esses dispositivos secundários de memória permitem o armazenamento permanente dos dados, ou seja, mesmo depois que o programa acaba ou até depois que o computador é reiniciado, os dados continuam existindo. Os principais dispositivos de armazenamento atualmente são:

  • Disco Rígido (HD)
  • Solid-State Drive (SSD)
  • Pen Drives

Os arquivos armazenados nestes dispositivos possuem sempre uma identificação (nome) e sua localização (normalmente em uma estrutura hierárquica de diretórios). Outros atributos como data e permissões de acesso também são normalmente usados no índice.

Acessando arquivos#

Arquivos são lidos como uma sequência de bytes. Um byte é um conjunto de 8 bits (BInary digiT), que são valores do tipo 0 ou 1. Bytes por si só não possuem significado nenhum, são simplesmente uma sequência de 0s e 1s. É necessário que um programa seja capaz de entender essa sequência de bytes do arquivo para extrair alguma informação.

Existem basicamente dois tipos de arquivos:

  • Arquivos de texto: os bytes representam caracteres. Por exemplo, os arquivos .py que criamos com o nosso código Python são arquivos de texto. Cada caractere do nosso código Python (incluindo espaços e pula linha) é representado por um byte e armazenado no nosso HD ou SSD.
  • Arquivos binários: cada byte pode ter um significado diferente. Por exemplo, em imagens é comum usar bytes para representar cores. No exemplo abaixo, os bytes do arquivo (à direita) são interpretados por um programa que é capaz de mostrar o resultado como uma imagem (à esquerda)
Arquivo de uma imagem em binário.

Neste handout vamos aprender a trabalhar com arquivos em Python. Ao final do handout você deve ser capaz de abrir um arquivo para (1) ler os dados armazenados; ou (2) escrever dados.

Arquivos em Python#

Antes de utilizar qualquer arquivo é necessário abri-lo. Para isso, existe a função open(), que recebe pelo menos dois argumentos: a localização do arquivo e o modo de abertura. Depois de utilizar o arquivo é muito importante lembrar de fechá-lo. Muitos problemas podem acontecer se você esquecer de fechar o programa. Para isso devemos usar a função close().

Exercise 1

Considere o código a seguir:

# Modo tradicional de ler um arquivo
arquivo = open('arquivo_texto.txt', 'r')
conteudo = arquivo.read()
arquivo.close() # O que acontece se não fechar?

# Imprime o conteúdo
print(conteudo)
Ao testar o código, o que foi impresso no terminal?

Answer

Quando estamos trabalhando com arquivos é comum obtermos o erro FileNotFoundError. Ele ocorre quando tentamos abrir (open()) um arquivo que não existe. É importante que o arquivo que você está tentando abrir esteja na mesma pasta que contém o seu programa.

No próximo exercício, vamos criar o arquivo arquivo_texto.txt.

Caminho (path) do arquivo

É possível abrir arquivos localizados em outras pastas do seu computador, mas nesse caso é necessário especificar o caminho do arquivo, ou seja, qual é a sequência de pastas que devem ser percorridas para se localizar esse arquivo.

Exercise 2

Crie um arquivo chamado arquivo_texto.txt e coloque o seguinte conteúdo no arquivo Lendo meu primeiro arquivo em Python! (pode ser no Spyder, VS Code, ou qualquer editor de texto de sua preferência - não use o Word, pois ele gera um arquivo muito mais complicado). Salve o programa acima na mesma pasta.

Execute seu programa. O que foi impresso?

Answer

O programa acima abre o arquivo arquivo_texto.txt, que acabamos de criar, para leitura (importante: ele deve existir na mesma pasta onde você está executando o seu programa), armazena o conteúdo na variável conteudo, fecha o arquivo e depois imprime todo o conteúdo do arquivo.

Ainda estou com problema de FileNotFoundError

Se você criou o arquivo `arquivo_texto.txt na mesma pasta que o código que você está executando. E mesmo assim está recebendo o erro FileNotFoundError", pode ser que o VS Code não esteja configurado para procurar o arquivo na pasta do seu código.

Para isso, basta configurar o VS Code.

  • No menu superior do VS Code, vá em Code > Preferences > Settings;
  • Ele abrirá uma aba chamada Settings;
  • Na aba Settings procure um campo de busca e digite python.terminal;
  • Ele listará alguns itens. Procure por Python>Terminal:Execute In File Dir;
  • Selecione a opção e teste seu programa novamente;

Abrindo arquivos com o with#

Como dissemos anteriormente, é muito importante se lembrar de fechar o arquivo depois de utilizá-lo. Na verdade, isso é tão importante que existe uma maneira de escrevermos um código que fecha o arquivo automaticamente depois que terminamos de utilizá-lo:

# Abre um arquivo para a leitura.
with open('arquivo_texto.txt', 'r') as arquivo:
    conteudo = arquivo.read()
# Quando sai do bloco do 'with', fecha o arquivo automaticamente.

# Imprime o conteúdo
print(conteudo)

A sintaxe do código acima é um pouco diferente, então vamos por partes. O with define um bloco dentro do qual o arquivo será utilizado. Assim que o bloco termina, o que é indicado pelo fim da indentação, o arquivo será automaticamente fechado. A função open() não foi alterada, mas agora ao invés de arquivo = open('arquivo_texto.txt', 'r') nós temos open('arquivo_texto.txt', 'r') as arquivo. O resultado será o mesmo: o arquivo aberto será armazenado na variável arquivo. Essa inversão da ordem é feita apenas em conjunto com o with.

Exercise 3

Ao testar a versão do programa acima, o que foi impresso?

Answer

Foi impresso Lendo meu primeiro arquivo em Python!. O resultado foi o mesmo da primeira versão.

Exercise 4

Considere o código a seguir:

with open('arquivo_texto.txt', 'r') as arquivo:
    conteudo = arquivo.read()

print(arquivo.read())
Ao testar o código, o que foi impresso no terminal?

Answer

O código acima apresenta o erro ValueError: I/O operation on closed file..

Perceba que na mensagem de erro, o Python informa que estamos tentando fazer a operação I/O (Input/Output) em um arquivo que está fechado.

Ou seja, o arquivo está aberto no bloco de código (trecho com indentação) do comando with. Como o comando print(arquivo.read()) não possui indentação, isso significa que nesse trecho de código o arquivo já foi fechado.

Exercise 5

Vimos duas formas diferentes de trabalhar com arquivos no Python.

Qual das alternativas abaixo NÃO é uma forma válida de trabalhar com arquivos.

Answer

O código abaixo apresenta erro de sintaxe ao ser executado:

arquivo = with open('arquivo_texto.txt', 'r')
conteudo = arquivo.read()
Ao utilizar o comando with devemos definir a variável arquivo ao final do comando: with open('arquivo_texto.txt', 'r') as arquivo:.

Além disso, também devemos nos lembrar que o comando with define um bloco dentro do qual o arquivo será utilizado.

Modos de abertura de um arquivo#

Comentamos que existem dois tipos de arquivo: arquivos binários e arquivos de texto. Nos exemplos acima nós trabalhamos com a leitura de um arquivo de texto. Para isso o modo de abertura do arquivo foi o 'r', ou seja, leitura (read). Para abrir um arquivo binário para leitura devemos utilizar o modo 'rb' (read binary). Tanto o modo 'r' quanto o modo 'rb' permitem apenas a leitura de um arquivo existente. Não é possível adicionar (escrever) nenhuma informação a ele.

Para adicionar dados a um arquivo devemos abri-lo com algum dos modos de escrita. Os modos disponíveis são 'w' e 'a'. O modo 'w' cria um novo arquivo no modo escrita (write). Importante: se já existir um arquivo com o mesmo nome ele apaga o antigo. O modo 'a' (append) é um modo de escrita alternativo que adiciona o novo conteúdo ao final do arquivo se ele já existir, sem apagar o conteúdo anterior

Exercise 6

Considere o código a seguir:

# Cria o arquivo para escrita (limpa o antigo se já existir)
with open('arquivo_texto.txt', 'w') as arquivo:
    # Escrevendo um texto
    arquivo.write("algum dado\n")

# Abre/Cria o arquivo para escrita SEM apagar o que tinha antes.
with open('arquivo_texto.txt', 'a') as arquivo:
    # Escrevendo um texto
    arquivo.write("novo dado\n")
Ao testar o código acima, qual o conteúdo do arquivo 'arquivo_texto.txt'?

Answer

O primeiro trecho de código with open cria um arquivo chamado "arquivo_texto.txt", se o arquivo já existir ele será substituído. Em seguida, adiciona o texto algum dado. Note que ao abrir o arquivo o \n não aparece, pois é o caractere utilizado para a quebra de linha (new line).

O segundo trecho de código with open abre o arquivo "arquivo_texto.txt", mantém o conteúdo existente e adiciona o texto novo dado ao final do arquivo.

Exercise 7

Considere o mesmo código, só que agora invertemos a ordem dos códigos with open. O primeiro with open estamos passando o argumento 'a' (append) e o segundo estamos passando o argumento 'w' (write).

with open('arquivo_texto.txt', 'a') as arquivo:
    arquivo.write("abrindo arquivo no modo 'a'\n")

with open('arquivo_texto.txt', 'w') as arquivo:
    arquivo.write("abrindo arquivo no modo 'w'\n")
Ao testar o código acima, qual o conteúdo do arquivo 'arquivo_texto.txt'?

Answer

O primeiro trecho de código with open, com o argumento 'a', abre o arquivo "arquivo_texto.txt", mantém o conteúdo existente e adiciona o texto novo dado ao final do arquivo.

O segundo trecho de código with open, com o argumento 'w', cria um arquivo chamado "arquivo_texto.txt", se o arquivo já existir ele será substituído. Em seguida, adiciona o texto abrindo arquivo no modo 'w'.

Desta forma, o conteúdo do arquivo será o texto abrindo arquivo no modo 'w'.

A seguir apresentamos um resumo dos principais modos de abertura de arquivos (para mais detalhes consulte a documentação):

  • 'r': modo de leitura de arquivo texto;
  • 'rb': modo de leitura de arquivo binário;
  • 'w': modo de escrita de arquivo texto;
  • 'wb': modo de escrita de arquivo binário;
  • 'a': modo de escrita de arquivo texto, sem apagar o conteúdo anterior;
  • 'ab': modo de escrita de arquivo binário, sem apagar o conteúdo anterior.

Salve o arquivo cancao_do_exilio.txt (disponível neste link) na mesma pasta onde você fez os outros testes deste handout. Depois disso, teste o programa abaixo:

Programa 1#

# Lendo tudo de uma vez
with open('cancao_do_exilio.txt', 'r') as arquivo:
    conteudo_completo = arquivo.read()
print(conteudo_completo)

No Programa 1 usamos o método para leitura de arquivo .read() que retorna todo o conteúdo do arquivo em formato de string.

A seguir vamos ver outros métodos de leitura de arquivo.

Exercise 8

Programa 2#

# Lendo apenas a primeira linha
with open('cancao_do_exilio.txt', 'r') as arquivo:
    primeira_linha = arquivo.readline()
print(primeira_linha)

Ao testar o código acima, o que foi impresso no terminal?

Answer

Ao testar o Programa 2, foi impresso Minha terra tem palmeiras,.

No Programa 1 usamos o método .read() que lê todo o conteúdo do arquivo.

Já no Programa 2 estamos utilizando o método .readline(), que faz a leitura de uma única linha. Neste caso, ele lê a primeira linha do arquivo.

Exercise 9

Considere o código a seguir:

with open('cancao_do_exilio.txt', 'r') as arquivo:
    primeira_linha = arquivo.readline()
    segunda_linha = arquivo.readline()
    terceira_linha = arquivo.readline()
print(primeira_linha)
print(segunda_linha)
print(terceira_linha)

Neste código, ainda utilizamos o método .readline(), mas chamamos várias vezes. Ao testar o código, o que foi impresso?

Answer

Ao testar o código do Programa 2, foi impresso:

Minha terra tem palmeiras,

Onde canta o Sabiá;

As aves, que aqui gorjeiam,

O método .readline() retorna a primeira linha do arquivo. Ao utilizar o método novamente, podemos perceber que ele retorna a segunda linha do arquivo. Desta forma, podemos perceber que a cada nova chamada o método retorno a próxima linha do arquivo.

Note que ao imprimir as variáveis primeira_linha, segunda_linha e terceira_linha apareceram linhas em branco entre cada linha. Isso acontece porque no arquivo original cada linha termina em um '\n', que indica que a linha terminou, mas o print também pula uma linha automaticamente, então sempre serão puladas duas linhas.

Exercise 10

Programa 3#

# Lendo de linha em linha (note o plural em readlines)
with open('cancao_do_exilio.txt', 'r') as arquivo:
    # linhas é uma lista de strings, cada linha é uma string diferente
    linhas = arquivo.readlines()
    # Verificando que linhas é uma lista de strings
    print(linhas)
    # Imprimindo de linha em linha
    for linha in linhas:
        print(linha)

Ao testar o código acima, qual o tipo de dado é armazenado na variável linhas?

Answer

A variável linhas armazena uma lista de strings. Cada string representando cada linha do arquivo.

Note que o método utilizado neste exercício está no plural .readlines().

Resumo dos métodos de arquivos:#

Abaixo você encontra um resumo dos principais métodos de arquivos. Para mais detalhes, consulte a documentação.

Para arquivos abertos no modo de leitura#

  • read: retorna todo o conteúdo do arquivo em uma única string;
  • readline: retorna uma string contendo apenas a próxima linha;
  • readlines: retorna uma lista de strings, contendo uma string para cada linha.

Para arquivos abertos no modo de escrita#

  • write: escreve no arquivo a string passada como argumento;
  • writelines: recebe uma lista de strings e escreve todas no arquivo.

Exercise 11

Resolva o exercício Conta palavras no arquivo.

Acessar exercício

Exercise 12

Resolva o exercício Bananas no arquivo.

Acessar exercício

O formato JSON#

O formato JSON é uma forma de trocar informação de modo estruturado, simples e rápido entre sistemas. Ele é muito parecido com um dicionário do Python, contudo o JSON é um texto (string) e não uma estrutura de dados. Por ser um texto, ele pode ser armazenado em um arquivo. Assim esses dados continuam existindo, mesmo depois que o programa termina. Exemplo:

alunos.json
{"Alunos":[
     { "nome": "João", "notas": [ 8, 9, 5 ]  },
     { "nome": "Maria", "notas": [ 8, 10, 7 ] },
     { "nome": "José", "notas": [ 10, 10, 9 ] }
]}

O JSON acima contém os nomes e notas de 3 alunos. Esse poderia ser o conteúdo de um arquivo de texto chamado, por exemplo, alunos.json. Para utilizar os dados presentes nele será necessário processar a string JSON para obter um dicionário. Para isso utilizamos o módulo json do Python:

testa_json.py
import json

with open('alunos.json', 'r') as arquivo_json:
    texto = arquivo_json.read()

print(texto)
# Para verificar que é realmente um texto (string),
# vamos usar um fatiamento:
print(texto[:15])

# Criando um dicionário a partir das informações no texto
dicionario = json.loads(texto)

# Para verificar que é um dicionário,
# vamos imprimir o valor armazenado na chave "Alunos"
print(dicionario['Alunos'])

# Adicionando um novo aluno no dicionário
novo_aluno = {'nome': 'Alice', 'notas': [10, 7, 8]}
dicionario['Alunos'].append(novo_aluno)

# Transformando de volta para JSON (texto)
novo_json = json.dumps(dicionario)

# Salvando o arquivo
with open('alunos.json', 'w') as arquivo_json:
    arquivo_json.write(novo_json)

# Abra o arquivo alunos.json e verifique seu conteúdo.

Exercise 13

Baixe o arquivo alunos.json disponível neste link. Salve-o na mesma pasta onde você está fazendo os testes deste handout. Abra o arquivo no Spyder, VS Code ou seu editor de texto favorito. Crie um novo arquivo chamado testa_json.py e copie o código do programa acima.

Ao testar o código, qual o conteúdo armazenado no arquivo alunos.json? (Obs.: Pode ser que o arquivo "alunos.json" não apresente a mesma quebra de linha apresentada nas alternativas abaixo.)

Answer

Ao testar o código, podemos verificar que o conteúdo do arquivo alunos.json é:

alunos.json
{"Alunos":[
     { "nome": "João", "notas": [ 8, 9, 5 ]  },
     { "nome": "Maria", "notas": [ 8, 10, 7 ] },
     { "nome": "José", "notas": [ 10, 10, 9 ] },
     { "nome": "Alice", "notas": [10, 7, 8] }
]}
O código acima, faz: - a leitura do conteúdo do arquivo "alunos.json". O conteúdo vem no formato de string. - Converte a string com o conteúdo do arquivo para um dicionário em Python. - Adiciona o dicionário {'nome': 'Alice', 'notas': [10, 7, 8]} a lista de alunos. - Converte o dicionário em string. - Salva a string no arquivo "alunos.json".

Exercise 14

Considere o código json.loads() utilizado no exercício do "testa_json.py". O que esse código faz?

(Dica: Se você não lembra o que o código faz, dê uma olhada novamente no código do arquivo "testa_json.py" e procure esse trecho de código.)

Answer

O código json.loads() converte uma string em um dicionário Python.

Exercise 15

Considere o código json.dumps() utilizado no exercício do "testa_json.py". O que esse código faz?

(Dica: Se você não lembra o que o código faz, dê uma olhada novamente no código do arquivo "testa_json.py" e procure esse trecho de código.)

Answer

O código json.dumps() converte um dicionário Python em uma string.

Exercise 16

Resolva o exercício Valor total do estoque.

Acessar exercício