Lendo Dados de Arquivos
Visão Geral
Perguntas
Como posso carregar o conteúdo de um arquivo no Python?
Como eu posso processar muitos arquivos com um único comando?
Objetivos
Conseguir carregar o conteúdo de um arquivo em uma string ou lista.
Conseguir converter dados carregados como strings em valores numéricos.
Conseguir escrever valores carregados no Python em um novo arquivo.
Ser capaz de escrever expressões de globbing que correspondem a um conjunto de arquivos.
Usar glob para criar listas de arquivos.
Escrever for loops para executar operações em arquivos, dados seus nomes em uma lista.
Use a função embutida open para ler arquivos em uma string.
Para ler um arquivo, usamos a expressão with open(...) as f, onde f é a variável na qual vamos carregar o conteúdo
do arquivo em uma string. Segue a mesma estrutura de um loop for:
with open('data/consumos/consumos_00.txt') as f:
string_de_dados = f.read()
print(string_de_dados)
O uso do with ... não é obrigatório, mas é recomendado. Podemos abrir e fechar arquivos uma linha por vez.
O bloco de código a seguir é equivalente ao anterior:
arquivo_de_entrada = open('data/consumos/consumos_00.txt')
string_de_dados = arquivo_entrada.read()
arquivo_de_entrada.close()
print(string_de_dados)
Use read para carregar um arquivo como uma string.
A variável f vai ter um método .read que permite carregar os dados como uma string.
Repare que a variável f poderia se chamar qualquer coisa:
with open('data/consumos/consumos_00.txt') as arquivo_entrada:
string_de_dados = arquivo_entrada.read()
print(type(string_de_dados))
Use readlines para carregar um arquivo como uma lista de linhas.
Ler um arquivo como string pode ser útil, mas muitas vezes queremos criar
coleções de valores (listas) com o conteúdo do arquivo. O método readlines
carrega o conteúdo do arquivo em uma lista, na qual cada elemento é uma linha do arquivo.
with open('data/consumos/consumos_00.txt') as f:
lista_de_dados = f.readlines()
print(type(lista_de_dados))
Os caracteres '\t' e '\n' simbolizam espaços em branco.
Diferente da nossa string_de_dados, se imprimirmos nossa lista, o resultado não é muito bonito:
print(lista_de_dados)
Isso acontece por que cada linha do nosso arquivo (e cada elemento na nossa lista) é uma string,
e não um número. Essas strings possuem o caracter '\n' no final. Esse caracter é utilizado para simbolizar
um espaço de nova linha:
print("Uma linha com espaço no final.\nOutra linha.")
O caracter TAB também simboliza um espaço em branco, mas de um TAB, ou parágrafo:
print("Antes do TAB:\tDepois.")
Recuperando Valores Numéricos
Para poder fazer operações numéricas com o conteúdo desses arquivos, precisamos de valores de tipo numéricos, e não strings.
Utilize conversão de tipos e o padrão acumulador para carregar o conteúdo do arquivoconsumos_00.txtem uma lista de floats.Solução
lista_floats = [] with open("data/consumos/consumos_00.txt") as f: lista_strings = f.readlines() for linha in lista_strings: lista_floats.append(float(linha))
Removendo espaços em branco
No exercício anterior, usamos conversão de tipos para converter as strings que carregamos do arquivo para remover o espaço em branco (
'\n'). No entanto, as strings também tem os métodosstripque podem fazer isso.linha_um = "\nUma linha com espaço em branco no início e fim.\n\n\n" linha_dois = "\nOutra linha, com espaço em branco no início." print(linha_um + linha_dois)Uma linha com espaço em branco no início e fim. Outra linha, com espaço em branco no início.Se aplicarmos o método
stripnalinha_um, removemos o espaço em branco do início e final da linha.:linha_um = "\nUma linha com espaço em branco no início e fim.\n\n\n" linha_dois = "\nOutra linha, com espaço em branco no início." print(linha_um.strip() + linha_dois)Uma linha com espaço em branco no início e fim. Outra linha, com espaço em branco no início.Também existe o método
lstrippara somente para espaços no início da linha, erstripsomente para espaços no fim:linha_um = "\nUma linha com espaço em branco no início e fim.\n\n\n" linha_dois = "\nOutra linha, com espaço em branco no início." print(linha_um.rstrip() + linha_dois.lstrip())Uma linha com espaço em branco no início e fim.Outra linha, com espaço em branco no início.
Use um for loop para processar arquivos dada uma lista com seus nomes.
- Um nome de arquivo é uma string de caracteres.
- Podemos criar uma lista de nomes de arquivos e rodar um
forloop.
lista_de_arquivos = [
"data/consumos/consumos_00.txt",
"data/consumos/consumos_01.txt",
"data/consumos/consumos_02.txt",
"data/consumos/consumos_03.txt",
"data/consumos/consumos_04.txt",
]
for arquivo in lista_de_arquivos:
numeros = []
with open(arquivo) as f:
linhas = f.readlines()
print("Nome do arquivo:", arquivo)
print("Número de medições:", len(linhas))
print("\n")
Nome do arquivo: data/consumos/consumos_00.txt
Número de medições: 54
Nome do arquivo: data/consumos/consumos_01.txt
Número de medições: 81
Nome do arquivo: data/consumos/consumos_02.txt
Número de medições: 70
Nome do arquivo: data/consumos/consumos_03.txt
Número de medições: 52
Nome do arquivo: data/consumos/consumos_04.txt
Número de medições: 62
No entanto, ter que criar manualmente a lista de arquivos pode ser bem custoso. Existem soluções práticas para isso.
Use glob.glob para encontrar conjuntos de arquivos cujos nomes correspondam a um padrão.
- Em UNIX/Linux, o termo “globbing” significa “corresponder um conjunto de arquivos a um padrão”.
- Os padrões mais comuns são:
*que significa “corresponde zero ou mais caracteres”.?que significa “corresponde pelo menos um caracter”.
- A biblioteca padrão do Python contém o módulo
globpara prover funcionalidade para encontrar padrões. - O módulo
globcontém uma função também chamadaglobpara corresponder padrões. - Por exemplo,
glob.glob('*.txt')corresponde a todos os arquivos no diretório atual cujos nomes terminam com.txt. - Resultado é uma lista (possivelmente vazia) de strings.
import glob
print('Todos os arquivos zippados no diretório `data`:', glob.glob('data/*.zip'))
['data/consumos.zip']
Encontre os Arquivos
Modifique o código acima para encontrar todos os arquivos com dados de consumos. Como podemos modificar essa busca para encontrar somente os arquivos 00 até 09?
Solução
Existem muitas buscas que podem dar certo, mas uma simples e direta é:
# Todos os arquivos glob.glob("data/consumos/*.txt")# De 00 até 09 glob.glob("data/consumos/consumos_0*.txt")
Use glob e for para processar lotes de arquivos.
- Ajuda bastante se os nomes dos arquivos forem nomeados de forma sistemática e consistente para que padrões simples achem os nomes corretos.
for arquivo in glob("data/consumos/*.txt"):
numeros = []
with open(arquivo) as f:
linhas = f.readlines()
print("Nome do arquivo:", arquivo)
print("Número de medições:", len(linhas))
print("\n")
Processando Lotes de Arquivos
Usando
globe um for loop, escreva um programa que:
- Calcule o número de medições em cada arquivo.
- Calcule o menor e maior consumo e cada arquivo.
- Imprima tudo em um loop.
Depois que conseguir, modifique seu código para imprimir:
- O nome do arquivo com mais registros.
- O nome do arquivo com o maior valor (e o valor.)
- O nome do arquivo com o menor valor (e o valor.)
Solução
lista_de_arquivos = glob("data/consumos/*.txt") for arquivo in lista_de_arquivos: numeros = [] with open(arquivo) as f: linhas = f.readlines() for numero in linhas: numeros.append(float(numero)) menor_consumo = min(numeros) maior_consumo = max(numeros) print("Nome do arquivo:", arquivo) print("Número de medições:", len(numeros)) print("Consumo máximo:", maior_consumo) print("Consumo mínimo:", menor_consumo) print("\n")Adicionando as outras métricas:
lista_de_arquivos = glob("data/consumos/*.txt") arquivo_mais_registros = "" arquivo_maximo_consumo = "" arquivo_minimo_consumo = "" mais_registros = 0 maximo_consumo = 0 minimo_consumo = 0 for arquivo in lista_de_arquivos: numeros = [] with open(arquivo) as f: linhas = f.readlines() for numero in linhas: numeros.append(float(numero)) n_medicoes = len(numeros) maior_consumo = max(numeros) menor_consumo = min(numeros) if n_medicoes > mais_registros: mais_registros = n_medicoes arquivo_mais_registros = arquivo if maior_consumo > maximo_consumo: maximo_consumo = maior_consumo arquivo_maximo_consumo = arquivo if minimo_consumo == 0 or menor_consumo < minimo_consumo: minimo_consumo = menor_consumo arquivo_minimo_consumo = arquivo print("Arquivo com mais medições:", arquivo_mais_registros, "com", mais_registros, "medições.") print("Arquivo com maior valor:", arquivo_maximo_consumo, maximo_consumo) print("Arquivo com menor valor:", arquivo_minimo_consumo, minimo_consumo) print("\n")Arquivo com mais medições: data/consumos/consumos_24.txt com 100 medições. Arquivo com maior valor: data/consumos/consumos_25.txt 117.99 Arquivo com menor valor: data/consumos/consumos_23.txt 69.0
Pontos-chave
Use a função embutida
openpara ler arquivos.Use
readpara carregar um arquivo como uma string.Use
readlinespara carregar um arquivo como uma lista de linhas.Os caracteres
' 'e' 'simbolizam espaços em branco.Use a função
open(..., mode='w')para escrever em arquivos.Use um
forloop para processar arquivos dada uma lista com seus nomes.Use
glob.globpara encontrar conjuntos de arquivos cujos nomes correspondam a um padrão.Use
globeforpara processar lotes de arquivos.