Iterador de archivos Python sobre un archivo binario con un lenguaje más reciente
En Python, para un archivo binario, puedo escribir esto:
buf_size=1024*64 # this is an important size...
with open(file, "rb") as f:
while True:
data=f.read(buf_size)
if not data: break
# deal with the data....
Con un archivo de texto que quiero leer línea por línea, puedo escribir esto:
with open(file, "r") as file:
for line in file:
# deal with each line....
Que es la abreviatura de:
with open(file, "r") as file:
for line in iter(file.readline, ""):
# deal with each line....
Este modismo está documentado en PEP 234 pero no he podido localizar un modismo similar para archivos binarios.
He intentado esto:
>>> with open('dups.txt','rb') as f:
... for chunk in iter(f.read,''):
... i+=1
>>> i
1 # 30 MB file, i==1 means read in one go...
Intenté poner iter(f.read(buf_size),'')
pero eso es un error de sintaxis debido a los paréntesis después del invocable en iter().
Sé que podría escribir un función, pero ¿hay alguna manera con el modismo predeterminado de for chunk in file:
donde puedo usar un tamaño de búfer frente a una línea orientada?
Gracias por soportar al novato de Python intentando escribir su primer script Python no trivial e idiomático.
2 answers
No conozco ninguna forma incorporada de hacer esto, pero una función wrapper es bastante fácil de escribir:
def read_in_chunks(infile, chunk_size=1024*64):
while True:
chunk = infile.read(chunk_size)
if chunk:
yield chunk
else:
# The chunk was empty, which means we're at the end
# of the file
return
Luego en el prompt interactivo:
>>> from chunks import read_in_chunks
>>> infile = open('quicklisp.lisp')
>>> for chunk in read_in_chunks(infile):
... print chunk
...
<contents of quicklisp.lisp in chunks>
Por supuesto, puede adaptar esto fácilmente para usar un bloque con:
with open('quicklisp.lisp') as infile:
for chunk in read_in_chunks(infile):
print chunk
Y puedes eliminar la sentencia if como esta.
def read_in_chunks(infile, chunk_size=1024*64):
chunk = infile.read(chunk_size)
while chunk:
yield chunk
chunk = infile.read(chunk_size)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-31 04:16:21
Intenta:
>>> with open('dups.txt','rb') as f:
... for chunk in iter((lambda:f.read(how_many_bytes_you_want_each_time)),''):
... i+=1
iter
necesita una función con cero argumentos.
- una llanura
f.read
leería todo el archivo, ya que falta el parámetrosize
; -
{[6] } significa llamar a una función y pasar su valor de retorno (datos cargados desde el archivo) a
iter
, por lo queiter
no obtiene una función en absoluto; -
(lambda:f.read(1234))
es una función que toma cero argumentos (nada entrelambda
y:
) y llama af.read(1234)
.
Hay equivalencia entre lo siguiente:
somefunction = (lambda:f.read(how_many_bytes_you_want_each_time))
Y
def somefunction(): return f.read(how_many_bytes_you_want_each_time)
Y teniendo uno de estos antes de tu código podrías escribir: iter(somefunction, '')
.
Técnicamente puedes saltarte los paréntesis alrededor de lambda, la gramática de python aceptará eso.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-11 21:48:48