Método de “línea en objeto de archivo” para leer archivos

Estoy tratando de encontrar la mejor manera de leer / procesar líneas para archivos súper grandes. Aquí solo bash

for line in f: 

Parte de mi guión es la siguiente:

 o=gzip.open(file2,'w') LIST=[] f=gzip.open(file1,'r'): for i,line in enumerate(f): if i%4!=3: LIST.append(line) else: LIST.append(line) b1=[ord(x) for x in line] ave1=(sum(b1)-10)/float(len(line)-1) if (ave1 < 84): del LIST[-4:] output1=o.writelines(LIST) 

Mi file1 es de alrededor de 10 GB; y cuando ejecuto el script, el uso de la memoria sigue aumentando a 15GB sin ningún tipo de salida. Eso significa que la computadora todavía está intentando leer todo el archivo en la memoria primero, ¿verdad? Esto realmente no es diferente a usar readlines()

Sin embargo, en la publicación: diferentes formas de leer datos de gran tamaño en python, Srika me dijo: The for line in f trata el objeto de archivo f como una iterable, que utiliza automáticamente la gestión de memoria e IO en búfer para que no tenga que preocuparse por los archivos grandes .

Pero, obviamente, todavía necesito preocuparme por los archivos grandes … Estoy realmente confundido. Gracias

Editar: Cada 4 líneas es una especie de grupo en mis datos. El propósito es hacer algunos cálculos en cada cuarta línea; y en base a ese cálculo, decida si necesitamos agregar esas 4 líneas. Así que escribir líneas es mi propósito.

Parece que al final de esta función, estás tomando todas las líneas que has leído en la memoria y luego las escribes en un archivo. Tal vez puedas probar este proceso:

  1. Lea las líneas que necesita en la memoria (las 3 primeras líneas).
  2. En la cuarta línea, agregue la línea y realice su cálculo.
  3. Si su cálculo es lo que está buscando, descargue los valores de su colección en el archivo.
  4. Independientemente de lo que sigue, cree una nueva instancia de colección.

No he probado esto , pero tal vez podría parecer algo como esto:

 o=gzip.open(file2,'w') f=gzip.open(file1,'r'): LIST=[] for i,line in enumerate(f): if i % 4 != 3: LIST.append(line) else: LIST.append(line) b1 = [ord(x) for x in line] ave1 = (sum(b1) - 10) / float(len(line) - 1 # If we've found what we want, save them to the file if (ave1 >= 84): o.writelines(LIST) # Release the values in the list by starting a clean list to work with LIST = [] 

EDITAR: Sin embargo, como un pensamiento, ya que su archivo es tan grande, puede que esta no sea la mejor técnica debido a todas las líneas que tendría que escribir en el archivo, pero puede valer la pena investigar.

La razón por la que la memoria mantiene inc. Incluso después de usar el enumerator es porque está utilizando LIST.append(line) . Eso básicamente acumula todas las líneas del archivo en una lista. Obviamente todo está sentado en la memoria. Necesitas encontrar una manera de no acumular líneas como esta. Lea, procese y pase a la siguiente.

Una forma más que podría hacer es leer su archivo en fragmentos (de hecho, leer 1 línea a la vez puede calificar en este criterio, 1 chunk == 1 línea), es decir, leer una pequeña parte del proceso del archivo, luego leer el siguiente fragmento, etc. aún mantengo que esta es la mejor manera de leer archivos en Python, grandes o pequeños.

 with open(...) as f: for line in f:  

La instrucción with maneja abrir y cerrar el archivo, incluso si se produce una excepción en el bloque interno. La for line in f trata el objeto de archivo f como iterable, que utiliza automáticamente la gestión de E / S en búfer para que no tenga que preocuparse por los archivos grandes.

Ya que agrega todas las líneas a la lista LIST y solo algunas veces le quita algunas líneas, la LIST se hace cada vez más larga. Todas esas líneas que almacenes en LIST tomarán memoria. No guarde todas las líneas en una lista si no quiere que ocupen memoria.

Además, su script no parece producir ningún resultado en ninguna parte, por lo que el punto de todo esto no es muy claro.

Ok, ya sabes cuál es tu problema por los otros comentarios / respuestas, pero déjame simplemente explicarlo.

Solo está leyendo una línea a la vez en la memoria, pero está almacenando una parte significativa de estas en la memoria agregándolas a una lista.

Para evitar esto, necesita almacenar algo en el sistema de archivos o en una base de datos (en el disco) para consultar más adelante si su algoritmo es lo suficientemente complicado.

Por lo que veo, parece que puedes escribir fácilmente la salida de forma incremental. es decir. Actualmente está utilizando una lista para almacenar líneas válidas para escribir en la salida , así como líneas temporales que puede eliminar en algún momento. Para ser eficiente con la memoria, debe escribir las líneas de su lista temporal tan pronto como sepa que estas son salidas válidas.

En resumen, use su lista para almacenar solo los datos temporales que necesita para realizar sus cálculos basados ​​en, y una vez que tenga algunos datos válidos listos para su salida, simplemente puede escribirlos en el disco y borrarlos de su memoria principal (en python, esto sería significa que ya no debería tener ninguna referencia a él.)

Si no usa la instrucción with , debe cerrar los controladores del archivo:

 o.close() f.close()