¿Cómo concateno archivos de texto en Python?
Tengo una lista de 20 nombres de archivos, como ['file1.txt', 'file2.txt', ...]
. Quiero escribir un script en Python para concatenar estos archivos en un archivo nuevo. Podría abrir cada archivo mediante f = open(...)
, leer línea por línea llamando f.readline()
y escribir cada línea en ese nuevo archivo. No me parece muy "elegante", especialmente la parte donde tengo que leer/escribir línea por línea.
¿Existe una forma más "elegante" de hacer esto en Python?
esto debería hacerlo
Para archivos grandes:
filenames = ['file1.txt', 'file2.txt', ...]
with open('path/to/output/file', 'w') as outfile:
for fname in filenames:
with open(fname) as infile:
for line in infile:
outfile.write(line)
Para archivos pequeños:
filenames = ['file1.txt', 'file2.txt', ...]
with open('path/to/output/file', 'w') as outfile:
for fname in filenames:
with open(fname) as infile:
outfile.write(infile.read())
… y otro interesante que se me ocurrió :
filenames = ['file1.txt', 'file2.txt', ...]
with open('path/to/output/file', 'w') as outfile:
for line in itertools.chain.from_iterable(itertools.imap(open, filnames)):
outfile.write(line)
Lamentablemente, este último método deja algunos descriptores de archivos abiertos, que el GC debería encargarse de todos modos. solo pensé que era interesante
Usar shutil.copyfileobj
.
Lee automáticamente los archivos de entrada fragmento por fragmento, lo cual es más eficiente y lee los archivos de entrada y funcionará incluso si algunos de los archivos de entrada son demasiado grandes para caber en la memoria:
import shutil
with open('output_file.txt','wb') as wfd:
for f in ['seg1.txt','seg2.txt','seg3.txt']:
with open(f,'rb') as fd:
shutil.copyfileobj(fd, wfd)
Para eso es exactamente la entrada de archivos :
import fileinput
with open(outfilename, 'w') as fout, fileinput.input(filenames) as fin:
for line in fin:
fout.write(line)
Para este caso de uso, en realidad no es mucho más simple que simplemente iterar sobre los archivos manualmente, pero en otros casos, tener un único iterador que itera sobre todos los archivos como si fueran un solo archivo es muy útil. (Además, el hecho de que fileinput
se cierre cada archivo tan pronto como esté listo significa que no es necesario hacerlo with
cada close
uno, pero eso es solo un ahorro de una línea, no es gran cosa).
Hay algunas otras características ingeniosas en fileinput
, como la capacidad de realizar modificaciones in situ de archivos simplemente filtrando cada línea.
Como se señala en los comentarios, y se comenta en otra publicación , fileinput
para Python 2.7 no funcionará como se indica. Aquí se realiza una pequeña modificación para que el código sea compatible con Python 2.7.
with open('outfilename', 'w') as fout:
fin = fileinput.input(filenames)
for line in fin:
fout.write(line)
fin.close()
outfile.write(infile.read()) # time: 2.1085190773010254s
shutil.copyfileobj(fd, wfd, 1024*1024*10) # time: 0.60599684715271s
Un simple punto de referencia muestra que el Shutil funciona mejor.