una txt linea leer importar gestion especifica español ejercicios dat como columnas archivos archivo abrir python file-io generator

txt - ¿Método perezoso para leer archivos grandes en Python?



leer una linea especifica de un archivo en python (11)

Tengo un archivo muy grande de 4GB y cuando intento leerlo, mi computadora se cuelga. Así que quiero leerlo pieza por pieza y luego de procesar cada pieza, almacene la pieza procesada en otro archivo y lea la siguiente pieza.

¿Hay algún método para yield estas piezas?

Me encantaría tener un método perezoso .


Creo que podemos escribir así:

def read_file(path, block_size=1024): with open(path, ''rb'') as f: while True: piece = f.read(block_size) if piece: yield piece else: return for piece in read_file(path): process_piece(piece)



Estoy en una situación algo similar. No está claro si conoces el tamaño del fragmento en bytes; Normalmente no lo hago, pero se conoce el número de registros (líneas) que se requiere:

def get_line(): with open(''4gb_file'') as file: for i in file: yield i lines_required = 100 gen = get_line() chunk = [i for i, j in zip(gen, range(lines_required))]

Actualización : gracias nosklo. Esto es lo que quise decir. Casi funciona, excepto que pierde una línea ''entre'' trozos.

chunk = [next(gen) for i in range(lines_required)]

Hace el truco sin perder ninguna línea, pero no se ve muy bien.


No se me permite comentar debido a mi baja reputación, pero la solución SilentGhosts debería ser mucho más fácil con file.readlines ([sizehint])

métodos de archivo python

edición: SilentGhost tiene razón, pero esto debería ser mejor que:

s = "" for i in xrange(100): s += file.next()


Para escribir una función perezosa, solo usa yield :

def read_in_chunks(file_object, chunk_size=1024): """Lazy function (generator) to read a file piece by piece. Default chunk size: 1k.""" while True: data = file_object.read(chunk_size) if not data: break yield data f = open(''really_big_file.dat'') for piece in read_in_chunks(f): process_data(piece)

Otra opción sería usar iter y una función auxiliar:

f = open(''really_big_file.dat'') def read1k(): return f.read(1024) for piece in iter(read1k, ''''): process_data(piece)

Si el archivo está basado en líneas, el objeto de archivo ya es un generador de líneas perezoso:

for line in open(''really_big_file.dat''): process_data(line)


Para procesar línea por línea, esta es una solución elegante:

def stream_lines(file_name): file = open(file_name) while True: line = file.readline() if not line: file.close() break yield line

Mientras no haya líneas en blanco.


Puedes usar el siguiente código.

file_obj = open(''big_file'')

open () devuelve un objeto de archivo

luego usa os.stat para obtener el tamaño

file_size = os.stat(''big_file'').st_size for i in range( file_size/1024): print file_obj.read(1024)


Ya hay muchas respuestas buenas, pero recientemente tuve un problema similar y la solución que necesitaba no se encuentra aquí, así que pensé que podría complementar este hilo.

El 80% del tiempo, necesito leer los archivos línea por línea. Luego, como se sugiere en esta answer , desea utilizar el objeto de archivo como un generador perezoso:

with open(''big.csv'') as f: for line in f: process(line)

Sin embargo, recientemente me topé con un csv muy grande (casi) de una sola línea, donde el separador de fila no era, en realidad, ''/n'' sino ''|'' .

  • La lectura línea por línea no era una opción, pero aún necesitaba procesarla fila por fila.
  • Convertir ''|'' a ''/n'' antes del procesamiento también estaba fuera de cuestión, porque algunos de los campos de este csv contenían ''/n'' (entrada de usuario de texto libre).
  • El uso de la biblioteca csv también se descartó porque el hecho de que, al menos en las primeras versiones de la biblioteca, es difícil leer la línea de entrada por línea .

Se me ocurrió el siguiente fragmento:

def rows(f, chunksize=1024, sep=''|''): """ Read a file where the row separator is ''|'' lazily. Usage: >>> with open(''big.csv'') as f: >>> for r in rows(f): >>> process(row) """ incomplete_row = None while True: chunk = f.read(chunksize) if not chunk: # End of file if incomplete_row is not None: yield incomplete_row break # Split the chunk as long as possible while True: i = chunk.find(sep) if i == -1: break # If there is an incomplete row waiting to be yielded, # prepend it and set it back to None if incomplete_row is not None: yield incomplete_row + chunk[:i] incomplete_row = None else: yield chunk[:i] chunk = chunk[i+1:] # If the chunk contained no separator, it needs to be appended to # the current incomplete row. if incomplete_row is not None: incomplete_row += chunk else: incomplete_row = chunk

Lo he probado con éxito en archivos grandes y con diferentes tamaños de trozos (incluso probé un tamaño de trozos de 1 byte, solo para asegurarme de que el algoritmo no depende del tamaño).


file.readlines () toma un argumento de tamaño opcional que se aproxima al número de líneas leídas en las líneas devueltas.

bigfile = open(''bigfilename'',''r'') tmp_lines = bigfile.readlines(BUF_SIZE) while tmp_lines: process([line for line in tmp_lines]) tmp_lines = bigfile.readlines(BUF_SIZE)


Si su computadora, sistema operativo y python son de 64 bits , entonces puede usar el módulo mmap para asignar el contenido del archivo a la memoria y acceder a él con índices y segmentos. Aquí un ejemplo de la documentación:

import mmap with open("hello.txt", "r+") as f: # memory-map the file, size 0 means whole file map = mmap.mmap(f.fileno(), 0) # read content via standard file methods print map.readline() # prints "Hello Python!" # read content via slice notation print map[:5] # prints "Hello" # update content using slice notation; # note that new content must have same size map[6:] = " world!/n" # ... and read again using standard file methods map.seek(0) print map.readline() # prints "Hello world!" # close the map map.close()

Si su computadora, sistema operativo o python son de 32 bits , entonces los archivos grandes de tamaño variable pueden reservar una gran parte de su espacio de direcciones y starve su programa de memoria.


f = ... # file-like object, i.e. supporting read(size) function and # returning empty string '''' when there is nothing to read def chunked(file, chunk_size): return iter(lambda: file.read(chunk_size), '''') for data in chunked(f, 65536): # process the data

ACTUALIZACIÓN: El enfoque se explica mejor en https://.com/a/4566523/38592