Solicitações é uma biblioteca muito boa. Gostaria de usá-lo para baixar arquivos grandes (> 1 GB). O problema é que não é possível manter o arquivo inteiro na memória, preciso lê-lo em pedaços. E este é um problema com o seguinte 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 alguma razão, não funciona dessa maneira. Ele ainda carrega a resposta na memória antes de salvá-la em um arquivo.
ATUALIZAR
Se você precisar de um cliente pequeno (Python 2.x /3.x) que possa baixar grandes arquivos do FTP, pode encontrá-lo aqui . Ele suporta multithreading e reconecta (ele monitora conexões) e também ajusta parâmetros de soquete para a tarefa de download.
fonte
chunk_size
é crucial. por padrão, é 1 (1 byte). isso significa que, para 1 MB, ele fará 1 milhão de iterações. docs.python-requests.org/en/latest/api/…f.flush()
parece desnecessário. O que você está tentando realizar usando-o? (seu uso de memória não será de 1,5 GB se você o soltar).f.write(b'')
(seiter_content()
pode retornar uma string vazia) deve ser inofensiva e, portanto, tambémif chunk
pode ser descartada.f.flush()
não libera dados para o disco físico. Ele transfere os dados para o sistema operacional. Geralmente, é suficiente, a menos que haja uma falha de energia.f.flush()
torna o código mais lento aqui sem motivo. A liberação ocorre quando o buffer do arquivo correspondente (aplicativo interno) está cheio. Se você precisar de gravações mais frequentes; passe o parâmetro buf.size paraopen()
.r.close()
É muito mais fácil se você usar
Response.raw
eshutil.copyfileobj()
:Isso transmite o arquivo para o disco sem usar memória excessiva, e o código é simples.
fonte
with
bloco (aninhado) para fazer a solicitação:with requests.get(url, stream=True) as r:
with requests.get()
foi mesclado em 07/06/2017! Sua sugestão é razoável para pessoas que têm solicitações 2.18.0 ou posterior. Reread
método:response.raw.read = functools.partial(response.raw.read, decode_content=True)
Não é exatamente o que o OP estava pedindo, mas ... é ridiculamente fácil fazer isso com
urllib
:Ou assim, se você deseja salvá-lo em um arquivo temporário:
Eu assisti o processo:
E vi o arquivo crescendo, mas o uso de memória ficou em 17 MB. Estou esquecendo de algo?
fonte
from urllib import urlretrieve
shutil.copyfileobj
com mais votos, veja meus e outros comentários láO tamanho do seu pedaço pode ser muito grande. Você já tentou descartá-lo - talvez 1024 bytes por vez? (também, você pode usar
with
para arrumar a sintaxe)Aliás, como você deduz que a resposta foi carregada na memória?
Soa como se python não está esvaziando os dados de arquivo, de outros SO perguntas que você poderia tentar
f.flush()
eos.fsync()
forçar a gravação de arquivo e memória livre;fonte
f.flush(); os.fsync()
possa forçar a gravação de uma memória livre.os.fsync(f.fileno())
def DownloadFile(url)