Eu tenho uma lista de 20 nomes de arquivos, como ['file1.txt', 'file2.txt', ...]
. Eu quero escrever um script Python para concatenar esses arquivos em um novo arquivo. Eu poderia abrir cada arquivo f = open(...)
, ler linha por linha chamando f.readline()
e escrever cada linha nesse novo arquivo. Não me parece muito "elegante", especialmente a parte em que tenho que ler // escrever linha por linha.
Existe uma maneira mais "elegante" de fazer isso no Python?
python
file-io
concatenation
JJ Beck
fonte
fonte
cat file1.txt file2.txt file3.txt ... > output.txt
. Em python, se você não gostareadline()
, semprereadlines()
ou simplesmenteread()
.cat file1.txt file2.txt file3.txt
comando usando osubprocess
módulo e pronto. Mas não tenho certeza secat
funciona no Windows.with
instrução para garantir que seus arquivos sejam fechados corretamente e itere sobre o arquivo para obter linhas, em vez de usarf.readline()
.Respostas:
Isso deve servir
Para arquivos grandes:
Para arquivos pequenos:
... e outro interessante que eu pensei :
Infelizmente, esse último método deixa alguns descritores de arquivos abertos, dos quais o GC deve cuidar de qualquer maneira. Eu só pensei que isso era interessante
fonte
Use
shutil.copyfileobj
.Ele lê automaticamente os arquivos de entrada pedaço por pedaço para você, o que é mais eficiente e a leitura dos arquivos de entrada e funcionará mesmo que alguns arquivos de entrada sejam muito grandes para caber na memória:
fonte
for i in glob.glob(r'c:/Users/Desktop/folder/putty/*.txt'):
bem, eu substituí a instrução for para incluir todos os arquivos no diretório, masoutput_file
comecei a crescer realmente enorme como em centenas de gb em tempo muito rápido.É exatamente para isso que serve o fileinput :
Para este caso de uso, não é realmente muito mais simples do que apenas repetir os arquivos manualmente, mas em outros casos, é muito útil ter um único iterador que itere sobre todos os arquivos como se fossem um único arquivo. (Além disso, o fato de que
fileinput
fecha cada arquivo assim que ele é feito significa que não há necessidade dewith
ouclose
cada um, mas isso é apenas uma poupança de uma linha, não que grande de um negócio.)Existem outros recursos interessantes
fileinput
, como a capacidade de fazer modificações no local dos arquivos apenas filtrando cada linha.Conforme observado nos comentários e discutido em outro post , o
fileinput
Python 2.7 não funcionará como indicado. Aqui, uma pequena modificação para tornar o código compatível com Python 2.7fonte
fileinput
é informada de que é uma maneira de transformar um simplessys.argv
(ou o que resta como argumento apósoptparse
/ etc.) Em um grande arquivo virtual para scripts triviais, e não pensa em usá-lo para nada else (ou seja, quando a lista não for argumentos de linha de comando). Ou eles aprender, mas, em seguida, esquecer-I manter re descobrindo-lo a cada ano ou dois ...for line in fileinput.input()
não é a melhor maneira de escolher, neste caso particular: o OP quer arquivos concatenar, não lê-los linha por linha que é um processo teoricamente mais tempo para executarEu não sei sobre elegância, mas isso funciona:
fonte
cat
pode levar uma lista de arquivos, portanto, não é necessário chamá-lo repetidamente. Você pode facilmente torná-lo seguro chamando emsubprocess.check_call
vez deos.system
O que há de errado com os comandos UNIX? (considerando que você não está trabalhando no Windows):
ls | xargs cat | tee output.txt
faz o trabalho (você pode chamá-lo de python com subprocesso, se quiser)fonte
cat * | tee output.txt
.cat file1.txt file2.txt | tee output.txt
1> /dev/null
ao final do comandoUma referência simples mostra que o obturador tem um desempenho melhor.
fonte
Uma alternativa à resposta do @ inspectorG4dget (melhor resposta até a data 29-03-2016). Eu testei com 3 arquivos de 436MB.
@ inspectorG4dget solução: 162 segundos
A seguinte solução: 125 segundos
A idéia é criar um arquivo em lote e executá-lo, aproveitando a "velha boa tecnologia". É semi-python, mas funciona mais rápido. Funciona para janelas.
fonte
Se você tiver muitos arquivos no diretório,
glob2
poderá ser uma opção melhor para gerar uma lista de nomes de arquivos em vez de escrevê-los manualmente.fonte
Confira o método .read () do objeto File:
http://docs.python.org/2/tutorial/inputoutput.html#methods-of-file-objects
Você poderia fazer algo como:
ou uma maneira python mais 'elegante':
que, de acordo com este artigo: http://www.skymind.com/~ocrow/python_string/ , também seria o mais rápido.
fonte
Se os arquivos não forem gigantescos:
Se os arquivos forem grandes demais para serem totalmente lidos e mantidos na RAM, o algoritmo deverá ser um pouco diferente para ler cada arquivo a ser copiado em um loop por pedaços de comprimento fixo, usando,
read(10000)
por exemplo.fonte
os.open
eos.read
, porque plainopen
usa os wrappers do Python em torno do stdio do C, o que significa que 1 ou 2 buffers extras estão no seu caminho.fonte
fonte