Requests es una biblioteca realmente bonita. Me gustaría usarlo para descargar archivos grandes (> 1 GB). El problema es que no es posible mantener todo el archivo en la memoria. Necesito leerlo en fragmentos. Y este es un problema con el siguiente código
import requests
def DownloadFile(url)
local_filename = url.split('/')[-1]
r = requests.get(url)
f = open(local_filename, 'wb')
for chunk in r.iter_content(chunk_size=512 * 1024):
if chunk: # filter out keep-alive new chunks
f.write(chunk)
f.close()
return
Por alguna razón no funciona de esta manera. Todavía carga la respuesta en la memoria antes de guardarla en un archivo.
ACTUALIZAR
Si necesita un cliente pequeño (Python 2.x /3.x) que puede descargar archivos grandes desde FTP, puede encontrarlo aquí . Admite subprocesos múltiples y reconexiones (supervisa las conexiones) y también ajusta los parámetros de socket para la tarea de descarga.
fuente
chunk_size
es crucial. por defecto es 1 (1 byte). eso significa que por 1 MB hará 1 millón de iteraciones. docs.python-requests.org/en/latest/api/…f.flush()
Parece innecesario ¿Qué estás tratando de lograr al usarlo? (su uso de memoria no será 1.5gb si lo deja caer).f.write(b'')
(siiter_content()
puede devolver una cadena vacía) debe ser inofensivo y, porif chunk
lo tanto, también podría descartarse.f.flush()
no descarga datos al disco físico. Transfiere los datos al sistema operativo. Por lo general, es suficiente a menos que haya una falla de energía.f.flush()
hace que el código sea más lento aquí sin ninguna razón. El vaciado ocurre cuando el búfer de archivo correspondiente (dentro de la aplicación) está lleno. Si necesita escrituras más frecuentes; pasar el parámetro buf.size aopen()
.r.close()
Es mucho más fácil si usa
Response.raw
yshutil.copyfileobj()
:Esto transmite el archivo al disco sin usar memoria excesiva, y el código es simple.
fuente
with
bloque (anidado) para realizar la solicitud:with requests.get(url, stream=True) as r:
with requests.get()
solo se fusionó el 2017-06-07. Su sugerencia es razonable para las personas que tienen Solicitudes 2.18.0 o posterior. Ref: github.com/requests/requests/issues/4136read
método:response.raw.read = functools.partial(response.raw.read, decode_content=True)
No es exactamente lo que OP preguntaba, pero ... es ridículamente fácil hacer eso con
urllib
:O de esta manera, si desea guardarlo en un archivo temporal:
Vi el proceso:
Y vi crecer el archivo, pero el uso de memoria se mantuvo en 17 MB. ¿Me estoy perdiendo de algo?
fuente
from urllib import urlretrieve
shutil.copyfileobj
con más votos, vea mis comentarios y los de otros allíEl tamaño de tu fragmento podría ser demasiado grande, ¿has intentado soltarlo, quizás 1024 bytes a la vez? (también, podría usar
with
para ordenar la sintaxis)Por cierto, ¿cómo deduce que la respuesta se ha cargado en la memoria?
Parece que Python no está vaciando los datos al archivo, de otras preguntas SO que podría intentar
f.flush()
yos.fsync()
forzar la escritura del archivo y la memoria libre;fuente
f.flush(); os.fsync()
podría forzar una escritura libre de memoria.os.fsync(f.fileno())
def DownloadFile(url)