los - que hace next en python
El iterador del archivo Python sobre un archivo binario con un idioma nuevo (2)
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 una abreviatura de:
with open(file, "r") as file:
for line in iter(file.readline, ""):
# deal with each line....
Esta expresión idiomática está documentada en PEP 234, pero no he podido encontrar un modismo similar para los 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 ese es un error de sintaxis debido a los paréntesis después del invocable en iter ().
Sé que podría escribir una función, pero ¿hay forma de utilizar el idioma for chunk in file:
defecto for chunk in file:
donde puedo usar un tamaño de buffer frente a una línea?
Gracias por aguantar al novato de Python que intenta escribir su primer guion de Python no trivial e idiomático.
No conozco ninguna forma integrada de hacerlo, pero una función de envoltura 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 aviso 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 a con bloque:
with open(''quicklisp.lisp'') as infile:
for chunk in read_in_chunks(infile):
print chunk
Y puedes eliminar la declaración 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)
Tratar:
>>> 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.
- un
f.read
simplef.read
todo el archivo, ya que falta el parámetro desize
; -
f.read(1024)
significa llamar a una función y pasar su valor de retorno (datos cargados desde el archivo) aiter
, por lo queiter
no obtiene una función en absoluto; -
(lambda:f.read(1234))
es una función que toma cero argumentos (nada entrelambda
yf.read(1234)
y llama af.read(1234)
.
Hay equivalencia entre los siguientes:
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 tener uno de estos antes de su código podría simplemente escribir: iter(somefunction, '''')
.
Técnicamente puedes saltear los paréntesis alrededor de lambda, la gramática de python lo aceptará.