¿Cómo concateno archivos de texto en Python?

Resuelto JJ Beck asked hace 11 años • 12 respuestas

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?

JJ Beck avatar Nov 29 '12 02:11 JJ Beck
Aceptado

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

inspectorG4dget avatar Nov 28 '2012 19:11 inspectorG4dget

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)
Meow avatar Nov 22 '2014 12:11 Meow

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 fileinputse cierre cada archivo tan pronto como esté listo significa que no es necesario hacerlo withcada closeuno, 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 , fileinputpara 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()
abarnert avatar Nov 28 '2012 20:11 abarnert
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.

haoming avatar Apr 26 '2018 08:04 haoming