write txt texto partir lista leer importar funcion formas editar crear como binarios archivos archivo python file-io concatenation

txt - formas de leer un archivo en python



Python concatenar archivos de texto (11)

¿Qué pasa con los comandos de UNIX? (dado que no estás trabajando en Windows):

ls | xargs cat | tee output.txt ls | xargs cat | tee output.txt hace el trabajo (puede llamarlo desde python con subproceso si lo desea)

Tengo una lista de 20 nombres de archivos, como [''file1.txt'', ''file2.txt'', ...] . Quiero escribir un script de Python para concatenar estos archivos en un nuevo archivo. Podría abrir cada archivo por f = open(...) , leer línea por línea llamando a 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.

¿Hay alguna 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 otra interesante que pensé :

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)

Tristemente, este último método deja algunos descriptores de archivos abiertos, de los cuales el GC debería encargarse de todos modos. Solo pensé que era interesante


No sé sobre elegancia, pero esto funciona:

import glob import os for f in glob.glob("file*.txt"): os.system("cat "+f+" >> OutFile.txt")


Para eso es exactamente la entrada de fileinput :

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 itere sobre todos los archivos como si fueran un solo archivo es muy útil. (Además, el hecho de que la entrada de fileinput cierra cada archivo tan pronto como está listo significa que no hay necesidad de close o close cada uno, pero eso es solo un ahorro de una línea, no tanto).

Hay otras funciones ingeniosas en la entrada de fileinput , como la capacidad de realizar modificaciones in situ de archivos simplemente filtrando cada línea.

Como se señaló en los comentarios, y se discutió en otra post , la fileinput de fileinput para Python 2.7 no funcionará como se indica. Aquí ligera modificación para que el código Python 2.7 sea compatible

with open(''outfilename'', ''w'') as fout: fin = fileinput.input(filenames) for line in fin: fout.write(line) fin.close()


Si los archivos no son gigantescos:

with open(''newfile.txt'',''wb'') as newf: for filename in list_of_files: with open(filename,''rb'') as hf: newf.write(hf.read()) # newf.write(''/n/n/n'') if you want to introduce # some blank lines between the contents of the copied files

Si los archivos son demasiado grandes para leerlos completamente y guardarlos en la memoria RAM, el algoritmo debe ser un poco diferente para leer cada archivo que se va a copiar en un bucle por fragmentos de longitud fija, usando read(10000) por ejemplo.


Si tiene muchos archivos en el directorio, entonces glob2 podría ser una mejor opción para generar una lista de nombres de archivos en lugar de escribirlos a mano.

import glob2 filenames = glob2.glob(''*.txt'') # list of all .txt files in the directory with open(''outfile.txt'', ''w'') as f: for file in filenames: with open(file) as infile: f.write(infile.read()+''/n'')


Una alternativa a @ inspectorG4dget respuesta (la mejor respuesta hasta la fecha 29-03-2016). Probé con 3 archivos de 436MB.

@ inspectorG4dget solución: 162 segundos

La siguiente solución: 125 segundos

from subprocess import Popen filenames = [''file1.txt'', ''file2.txt'', ''file3.txt''] fbatch = open(''batch.bat'',''w'') str ="type " for f in filenames: str+= f + " " fbatch.write(str + " > file4results.txt") fbatch.close() p = Popen("batch.bat", cwd=r"Drive:/Path/to/folder") stdout, stderr = p.communicate()

La idea es crear un archivo por lotes y ejecutarlo, aprovechando la "vieja y buena tecnología". Es semi-python pero funciona más rápido. Funciona para windows.


Use shutil.copyfileobj . Debería ser más eficiente.

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, 1024*1024*10) #10MB per writing chunk to avoid reading big file into memory.


def concatFiles(): path = ''input/'' files = os.listdir(path) for idx, infile in enumerate(files): print ("File #" + str(idx) + " " + infile) concat = ''''.join([open(path + f).read() for f in files]) with open("output_concatFile.txt", "w") as fo: fo.write(path + concat) if __name__ == "__main__": concatFiles()


outfile.write(infile.read()) 2.1085190773010254s shutil.copyfileobj(fd, wfd, 1024*1024*10) 0.60599684715271s

Un punto de referencia simple muestra que el shutil tiene un mejor rendimiento.