¿Cómo puedo leer archivos de texto grandes en Python, línea por línea, sin cargarlos en la memoria?

Necesito leer un archivo grande, línea por línea. Digamos que el archivo tiene más de 5 GB y necesito leer cada línea, pero obviamente no quiero usar readlines() porque creará una lista muy grande en la memoria.

¿Cómo funcionará el siguiente código para este caso? ¿Se xreadlines leyendo las xreadlines una a una en la memoria? ¿Se necesita la expresión del generador?

 f = (line for line in open("log.txt").xreadlines()) # how much is loaded in memory? f.next() 

Además, ¿qué puedo hacer para leer esto en orden inverso, al igual que el comando de tail Linux?

Encontré:

http://code.google.com/p/pytailer/

y

” Cabeza de python, cola y lectura hacia atrás mediante líneas de un archivo de texto ”

Ambos trabajaron muy bien!

Proporcioné esta respuesta porque Keith, aunque sucinta, no cierra el archivo explícitamente

 with open("log.txt") as infile: for line in infile: do_something_with(line) 

Todo lo que necesita hacer es usar el objeto de archivo como un iterador.

 for line in open("log.txt"): do_something_with(line) 

Aún mejor es usar el administrador de contexto en las últimas versiones de Python.

 with open("log.txt") as fileobject: for line in fileobject: do_something_with(line) 

Esto cerrará automáticamente el archivo también.

Un enfoque de la vieja escuela:

 fh = open(file_name, 'rt') line = fh.readline() while line: # do stuff with line line = fh.readline() fh.close() 

Es mejor utilizar un iterador en su lugar. Relevante: http://docs.python.org/library/fileinput.html

De los documentos:

 import fileinput for line in fileinput.input("filename"): process(line) 

Esto evitará copiar todo el archivo en la memoria de una vez.

No podía creer que pudiera ser tan fácil como la respuesta de @ john-la-rooy lo hizo parecer. Entonces, recreé el comando cp usando la lectura y escritura línea por línea. Es LOCO RÁPIDO.

 #!/usr/bin/env python3.6 import sys with open(sys.argv[2], 'w') as outfile: with open(sys.argv[1]) as infile: for line in infile: outfile.write(line) 

Esto es lo que haces si no tienes nuevas líneas en el archivo:

 with open('large_text.txt') as f: while True: c = f.read(1024) if not c: break print(c) 

El proyecto de incendio ha recorrido un largo camino en los últimos 6 años. Tiene una API simple que cubre un subconjunto útil de características de pandas.

dask.dataframe se encarga de fragmentar internamente, admite muchas operaciones paralelizables y le permite exportar rebanadas a pandas fácilmente para operaciones en memoria.

 import dask.dataframe as dd df = dd.read_csv('filename.csv') df.head(10) # return first 10 rows df.tail(10) # return last 10 rows # iterate rows for idx, row in df.iterrows(): ... # group by my_field and return mean df.groupby(df.my_field).value.mean().compute() # slice by column df[df.my_field=='XYZ'].compute() 

¿Qué tal esto? Divide tu archivo en partes y luego léelo línea por línea, porque cuando lees un archivo, tu sistema operativo almacenará en caché la siguiente línea. Si está leyendo el archivo línea por línea, no está haciendo un uso eficiente de la información almacenada en caché.

En su lugar, divida el archivo en partes, cargue toda la parte en la memoria y luego realice el procesamiento.

 def chunks(file,size=1024): while 1: startat=fh.tell() print startat #file's object current position from the start fh.seek(size,1) #offset from current postion -->1 data=fh.readline() yield startat,fh.tell()-startat #doesnt store whole list in memory if not data: break if os.path.isfile(fname): try: fh=open(fname,'rb') except IOError as e: #file --> permission denied print "I/O error({0}): {1}".format(e.errno, e.strerror) except Exception as e1: #handle other exceptions such as attribute errors print "Unexpected error: {0}".format(e1) for ele in chunks(fh): fh.seek(ele[0])#startat data=fh.read(ele[1])#endat print data 

¡Gracias! Recientemente me he convertido a Python 3 y me he sentido frustrado al usar readlines (0) para leer archivos grandes. Esto solucionó el problema. Pero para obtener cada línea, tuve que hacer un par de pasos adicionales. Cada línea estaba precedida por una “b”, que supongo que estaba en formato binario. Usando “decode (utf-8)” lo cambié ascii.

Luego tuve que eliminar un “= \ n” en el medio de cada línea.

Luego partí las líneas en la nueva línea.

 b_data=(fh.read(ele[1]))#endat This is one chunk of ascii data in binary format a_data=((binascii.b2a_qp(b_data)).decode('utf-8')) #Data chunk in 'split' ascii format data_chunk = (a_data.replace('=\n','').strip()) #Splitting characters removed data_list = data_chunk.split('\n') #List containing lines in chunk #print(data_list,'\n') #time.sleep(1) for j in range(len(data_list)): #iterate through data_list to get each item i += 1 line_of_data = data_list[j] print(line_of_data) 

Aquí está el código que comienza justo encima de “imprimir datos” en el código de Arohi.

He demostrado un enfoque de acceso aleatorio de nivel de byte paralelo aquí en esta otra pregunta:

Obtención de número de líneas en un archivo de texto sin readlines

Algunas de las respuestas ya proporcionadas son agradables y concisas. Me gustan algunos de ellos. Pero realmente depende de lo que quieras hacer con los datos que están en el archivo. En mi caso, solo quería contar líneas, lo más rápido posible en archivos de texto grandes. Por supuesto, mi código puede modificarse para hacer otras cosas, como cualquier código.

Aquí está el código para cargar archivos de texto de cualquier tamaño sin causar problemas de memoria. Es compatible con archivos de tamaño gigabytes

https://gist.github.com/iyvinjose/e6c1cb2821abd5f01fd1b9065cbc759d

descargue el archivo data_loading_utils.py e impórtelo en su código

uso

 import data_loading_utils.py.py file_name = 'file_name.ext' CHUNK_SIZE = 1000000 def process_lines(data, eof, file_name): # check if end of file reached if not eof: # process data, data is one single line of the file else: # end of file reached data_loading_utils.read_lines_from_file_as_data_chunks(file_name, chunk_size=CHUNK_SIZE, callback=self.process_lines) 

El método process_lines es la función de callback. Se llamará para todas las líneas, con los datos de parámetros que representan una sola línea del archivo a la vez.

Puede configurar la variable CHUNK_SIZE en función de las configuraciones de hardware de su máquina.

Por favor intente esto:

 with open('filename','r',buffering=100000) as f: for line in f: print line 
 f=open('filename','r').read() f1=f.split('\n') for i in range (len(f1)): do_something_with(f1[i]) 

espero que esto ayude.