Para escribir una función perezosa, solo use 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
with open('really_big_file.dat') as f:
for piece in read_in_chunks(f):
process_data(piece)
Otra opción sería usar iter
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 del archivo ya es un generador de líneas diferido:
for line in open('really_big_file.dat'):
process_data(line)
f = open('really_big_file.dat')
es solo un puntero sin consumo de memoria? (Quiero decir que la memoria consumida es la misma independientemente del tamaño del archivo). ¿Cómo afectará el rendimiento si uso urllib.readline () en lugar de f.readline ()?rb
como mencionó @Tal Weiss; y falta unafile.close()
declaración (podría usarwith open('really_big_file.dat', 'rb') as f:
para lograr lo mismo; Vea aquí para otra implementación concisa'rb'
es decir, no falta.'b'
datos, es muy probable que se corrompan . Desde los documentos -Python on Windows makes a distinction between text and binary files; [...] it’ll corrupt binary data like that in JPEG or EXE files. Be very careful to use binary mode when reading and writing such files.
Si su computadora, sistema operativo y python son de 64 bits , entonces puede usar el módulo mmap para mapear el contenido del archivo en la memoria y acceder a él con índices y sectores. Aquí un ejemplo de la documentación:
Si su computadora, sistema operativo o python son de 32 bits , entonces el mapeo de archivos grandes puede reservar grandes partes de su espacio de direcciones y privar a su programa de memoria.
fuente
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.fuente
.read()
no.readlines()
. Si el archivo es binario, no tendrá saltos de línea.Ya hay muchas buenas respuestas, pero si su archivo completo está en una sola línea y aún desea procesar "filas" (en lugar de bloques de tamaño fijo), estas respuestas no lo ayudarán.
El 99% del tiempo, es posible procesar archivos línea por línea. Luego, como se sugiere en esta respuesta , puede usar el objeto de archivo en sí mismo como generador diferido:
Sin embargo, una vez me encontré con un archivo muy, muy grande (casi) de una sola línea, donde el separador de filas no era
'\n'
sino'|'
.'|'
a'\n'
antes del procesamiento también estaba fuera de discusión, porque algunos de los campos de este csv contenían'\n'
(entrada del usuario de texto libre).Para este tipo de situaciones, creé el siguiente fragmento:
Pude usarlo con éxito para resolver mi problema. Ha sido ampliamente probado, con varios tamaños de trozos.
Test suite, para aquellos que quieran convencerse a sí mismos.
fuente
ACTUALIZACIÓN: El enfoque se explica mejor en https://stackoverflow.com/a/4566523/38592
fuente
Consulte la documentación oficial de Python https://docs.python.org/zh-cn/3/library/functions.html?#iter
Quizás este método sea más pitónico:
fuente
Creo que podemos escribir así:
fuente
No puedo 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 de Python
editar: SilentGhost tiene razón, pero esto debería ser mejor que:
fuente
Estoy en una situación algo similar. No está claro si conoce el tamaño del fragmento en bytes; Usualmente no, pero se conoce la cantidad de registros (líneas) que se requiere:
Actualización : Gracias nosklo. Esto es lo que quise decir. Casi funciona, excepto que pierde una línea 'entre' trozos.
¿El truco sin perder ninguna línea, pero no se ve muy bien?
fuente
Para procesar línea por línea, esta es una solución elegante:
Mientras no haya líneas en blanco.
fuente
open
ya le ofrece. Un archivo ya es un iterador sobre sus líneas.Puedes usar el siguiente código.
open () devuelve un objeto de archivo
luego use os.stat para obtener el tamaño
fuente