Eu quero iterar sobre cada linha de um arquivo inteiro. Uma maneira de fazer isso é lendo o arquivo inteiro, salvando-o em uma lista e passando pela linha de interesse. Este método usa muita memória, então estou procurando uma alternativa.
Meu código até agora:
for each_line in fileinput.input(input_file):
do_something(each_line)
for each_line_again in fileinput.input(input_file):
do_something(each_line_again)
Executar este código dá uma mensagem de erro: device active
.
Alguma sugestão?
O objetivo é calcular a similaridade de seqüências de pares, ou seja, para cada linha do arquivo, desejo calcular a distância de Levenshtein com todas as outras linhas.
Respostas:
A maneira correta e totalmente Python de ler um arquivo é a seguinte:
A
with
instrução trata da abertura e do fechamento do arquivo, inclusive se uma exceção for gerada no bloco interno. Elefor line in f
trata o objeto de arquivof
como iterável, que usa automaticamente E / S em buffer e gerenciamento de memória para que você não precise se preocupar com arquivos grandes.fonte
for line in f:
está funcionando? Quero dizer, como iterar sobre o objeto de arquivo é possível?__iter__
, que informa o que fazer. Os objetos de arquivo definem esse método especial para retornar um iterador sobre as linhas. (Grosso modo).Duas maneiras eficientes de memória na ordem de classificação (a primeira é a melhor) -
with
- suportado no python 2.5 e superioryield
se você realmente quer ter controle sobre o quanto ler1. uso de
with
with
é a maneira pythonic agradável e eficiente de ler arquivos grandes. vantagens - 1) o objeto de arquivo é fechado automaticamente após sair dowith
bloco de execução. 2) manipulação de exceção dentro dowith
bloco. 3) ofor
loop de memória percorre of
objeto de arquivo linha por linha. internamente, realiza E / S em buffer (para otimizar operações caras de E / S) e gerenciamento de memória.2. uso de
yield
Às vezes, pode-se querer um controle mais refinado sobre o quanto ler em cada iteração. Nesse caso, use iter & yield . Observe que com esse método é necessário fechar explicitamente o arquivo no final.
Armadilhas e por uma questão de exaustividade - os métodos abaixo não são tão bons nem elegantes para ler arquivos grandes, mas leia para obter uma compreensão completa.
No Python, a maneira mais comum de ler linhas de um arquivo é fazer o seguinte:
Quando isso é feito, no entanto, a
readlines()
função (o mesmo se aplica àread()
função) carrega o arquivo inteiro na memória e itera sobre ele. Uma abordagem um pouco melhor (os dois primeiros métodos mencionados são os melhores) para arquivos grandes é usar ofileinput
módulo, da seguinte maneira:a
fileinput.input()
chamada lê as linhas sequencialmente, mas não as mantém na memória depois de serem lidas ou simplesmente por isso, já quefile
em python é iterável.Referências
fonte
for line in open(...).readlines(): <do stuff>
. Por que você?! Você acabou de perder todos os benefícios do IO inteligente de buffer do Ithon, sem nenhum benefício.readlines
e explicando por que não é uma coisa boa a se fazer (porque ele lê o arquivo na memória) e depois explicando o que ofileinput
módulo faz e por que você convém usá-lo sobre os outros métodos, explicando como o arquivo em partes melhora a IO e dando um exemplo da função de pedaços (mas mencionando que o Python já faz isso por você, para que você não precise). Mas apenas cinco maneiras de resolver um problema simples, quatro dos quais estão errados nesse caso, não é bom.Para retirar novas linhas:
Com o apoio de nova linha universal todas as linhas do arquivo de texto parece que vai ser terminada com
'\n'
, quaisquer que sejam os terminadores no arquivo,'\r'
,'\n'
, ou'\r\n'
.EDIT - Para especificar o suporte universal de nova linha:
open(file_path, mode='rU')
- obrigatório [obrigado @Dave ]open(file_path, mode='rU')
- opcionalopen(file_path, newline=None)
- opcionalO
newline
parâmetro é suportado apenas no Python 3 e o padrão éNone
. Omode
parâmetro é padronizado'r'
em todos os casos. AU
esta obsoleta em Python 3. Em Python 2 no Windows algum outro mecanismo parece traduzir\r\n
para\n
.Documentos:
Para preservar terminadores de linha nativos:
O modo binário ainda pode analisar o arquivo em linhas com
in
. Cada linha terá quaisquer terminadores existentes no arquivo.Graças a @katrielalex 's resposta , do Python open () doc, e iPython experimentos.
fonte
open(file_path, 'rU')
que habilitar novas linhas universais.Esta é uma maneira possível de ler um arquivo em python:
não aloca uma lista completa. Ele itera sobre as linhas.
fonte
with open(input_file) as f:
. Isso poupaf.close()
e garante que você não se esqueça de fechá-lo acidentalmente. Evita vazamentos de memória e tudo, muito importante ao ler arquivos.Algum contexto na frente de onde eu estou vindo. Os trechos de código estão no final.
Quando posso, prefiro usar uma ferramenta de código aberto como o H2O para fazer leituras paralelas de arquivos CSV de alto desempenho, mas essa ferramenta é limitada no conjunto de recursos. Acabo escrevendo muito código para criar pipelines de ciência de dados antes de alimentar o cluster de H2O para o aprendizado supervisionado adequado.
Tenho lido arquivos como o conjunto de dados HIGGS de 8 GB do repositório UCI e até arquivos CSV de 40 GB para fins de ciência de dados significativamente mais rapidamente, adicionando muito paralelismo ao objeto de pool da biblioteca de multiprocessamento e à função de mapa. Por exemplo, o agrupamento com pesquisas de vizinhos mais próximos e também os algoritmos de agrupamento DBSCAN e Markov requer alguma sutileza de programação paralela para contornar alguns problemas seriamente desafiadores da memória e do relógio de parede.
Eu geralmente gosto de dividir o arquivo em linhas em partes usando as ferramentas gnu primeiro e depois a glob-filemask todas para encontrar e ler em paralelo no programa python. Eu uso algo como 1000 arquivos parciais comumente. Fazer esses truques ajuda imensamente com a velocidade de processamento e os limites de memória.
O dataframe.read_csv do pandas é de thread único, para que você possa executar esses truques para tornar o panda muito mais rápido executando um map () para execução paralela. Você pode usar o htop para ver que, com os antigos pandas sequenciais dataframe.read_csv, 100% da CPU em apenas um núcleo é o gargalo real no pd.read_csv, e não o disco.
Devo acrescentar que estou usando um SSD no barramento rápido da placa de vídeo, não um HD giratório no barramento SATA6, além de 16 núcleos de CPU.
Além disso, outra técnica que eu descobri que funciona muito bem em alguns aplicativos é a leitura paralela de arquivos CSV em um arquivo gigante, iniciando cada trabalhador com um deslocamento diferente no arquivo, em vez de pré-dividir um arquivo grande em muitos arquivos de peça. Use o arquivo python seek () e tell () em cada trabalhador paralelo para ler o arquivo de texto grande em tiras, em diferentes locais de deslocamento de bytes e de início e de bytes no arquivo grande, tudo ao mesmo tempo simultaneamente. Você pode fazer uma localização regex nos bytes e retornar a contagem de feeds de linha. Esta é uma soma parcial. Finalmente, some as somas parciais para obter a soma global quando a função de mapa retornar após a conclusão dos trabalhadores.
A seguir, alguns exemplos de benchmarks usando o truque de deslocamento de bytes paralelos:
Eu uso 2 arquivos: HIGGS.csv é 8 GB. É do repositório de aprendizado de máquina da UCI. all_bin .csv tem 40,4 GB e é do meu projeto atual. Eu uso dois programas: o programa GNU wc, que acompanha o Linux, e o programa python fastread.py puro, que eu desenvolvi.
Isso significa uma velocidade de slurping de arquivo de 4,5 GB / s ou 45 Gb / s. Não há disco rígido girando, meu amigo. Na verdade, é um SSD Samsung Pro 950.
Abaixo está a referência de velocidade para o mesmo arquivo sendo contado em linha pelo gnu wc, um programa compilado em C puro.
O legal é que você pode ver que meu programa python puro correspondia essencialmente à velocidade do programa C compilado pelo gnu wc nesse caso. Python é interpretado, mas C é compilado, então esse é um feito bastante interessante de velocidade, acho que você concorda. Obviamente, o wc realmente precisa ser alterado para um programa paralelo e, em seguida, seria realmente melhor do que o meu programa python. Mas como está hoje, o gnu wc é apenas um programa seqüencial. Você faz o que pode e o python pode fazer paralelo hoje. A compilação do Cython pode me ajudar (por outro tempo). Os arquivos mapeados na memória também não foram explorados.
Conclusão: A velocidade é boa para um programa python puro comparado a um programa em C. No entanto, não é bom o suficiente usar o programa python puro sobre o programa C, pelo menos para fins de contagem de linha. Geralmente, a técnica pode ser usada para outro processamento de arquivo, portanto esse código python ainda é bom.
Pergunta: Compilar o regex apenas uma vez e passá-lo a todos os trabalhadores aumentará a velocidade? Resposta: A pré-compilação do Regex NÃO ajuda neste aplicativo. Suponho que a razão é que a sobrecarga da serialização e criação de processos para todos os trabalhadores esteja dominando.
Mais uma coisa. A leitura paralela de arquivos CSV ajuda mesmo? O disco é o gargalo ou a CPU? Muitas das chamadas respostas mais bem classificadas no stackoverflow contêm a sabedoria comum do desenvolvedor de que você só precisa de um thread para ler um arquivo, o melhor que pode fazer, dizem eles. Eles têm certeza?
Vamos descobrir:
Ah sim, sim. A leitura paralela de arquivos funciona muito bem. Bem, lá vai você!
Ps. Caso alguns de vocês quisessem saber, e se o balanceFactor fosse 2 ao usar um único processo de trabalho? Bem, é horrível:
Partes principais do programa python fastread.py:
A definição para PartitionDataToWorkers é apenas um código seqüencial comum. Eu o deixei de fora caso alguém mais quisesse praticar como é a programação paralela. Dei de graça as partes mais difíceis: o código paralelo testado e funcionando, para seu benefício de aprendizado.
Obrigado a: O projeto H2O de código aberto, de Arno e Cliff e a equipe de H2O, por seus ótimos softwares e vídeos instrutivos, que me deram a inspiração para este leitor de offset de bytes paralelos de alto desempenho python puro, como mostrado acima. O H2O faz a leitura paralela de arquivos usando java, é passível de chamada pelos programas python e R e é louco, rápido, mais rápido do que qualquer coisa no planeta ao ler grandes arquivos CSV.
fonte
O Katrielalex forneceu o caminho para abrir e ler um arquivo.
No entanto, a maneira como o algoritmo funciona, lê o arquivo inteiro para cada linha do arquivo. Isso significa que a quantidade geral de leitura de um arquivo - e computando a distância de Levenshtein - será feita N * N se N for a quantidade de linhas no arquivo. Como você está preocupado com o tamanho do arquivo e não deseja mantê-lo na memória, estou preocupado com o tempo de execução quadrático resultante . Seu algoritmo está na classe O (n ^ 2) de algoritmos que geralmente podem ser aprimorados com especialização.
Suspeito que você já conheça a troca de memória versus tempo de execução aqui, mas talvez deseje investigar se existe uma maneira eficiente de calcular várias distâncias de Levenshtein em paralelo. Nesse caso, seria interessante compartilhar sua solução aqui.
Quantas linhas seus arquivos possuem e em que tipo de máquina (memória e poder da CPU) seu algoritmo deve ser executado, e qual é o tempo de execução tolerado?
O código seria semelhante a:
Mas as perguntas são: como você armazena as distâncias (matriz?) E pode obter uma vantagem de preparar, por exemplo, a linha_externa para processamento ou armazenar em cache alguns resultados intermediários para reutilização.
fonte
Se você deseja, por exemplo, verificar uma linha específica para um comprimento maior que 10, trabalhe com o que você já tem disponível.
fonte
Na documentação do python para fileinput .input ():
Além disso, a definição da função é:
lendo nas entrelinhas, isso me diz que
files
pode ser uma lista para que você possa ter algo como:Veja aqui para mais informações
fonte
Eu recomendo fortemente não usar o carregamento de arquivo padrão, pois é terrivelmente lento. Você deve examinar as funções numpy e as funções IOpro (por exemplo, numpy.loadtxt ()).
http://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html
https://store.continuum.io/cshop/iopro/
Em seguida, você pode dividir sua operação em pares em pedaços:
É quase sempre muito mais rápido carregar dados em pedaços e depois executar operações de matriz nele do que fazê-lo elemento por elemento !!
fonte
Precisa ler frequentemente um arquivo grande da última posição?
Eu criei um script usado para cortar um arquivo access.log do Apache várias vezes ao dia. Então, eu precisava definir um cursor de posição na última linha analisada durante a última execução . Para este fim, eu usei
file.seek()
efile.seek()
métodos que permite o armazenamento do cursor no arquivo.Meu código:
fonte
A melhor maneira de ler arquivos grandes, linha por linha, é usar a função enumerar python
fonte