Requests - это действительно хорошая библиотека. Я хотел бы использовать его для загрузки больших файлов (> 1 ГБ). Проблема в том, что невозможно сохранить весь файл в памяти, мне нужно прочитать его порциями. И это проблема со следующим кодом
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
По какой-то причине это не работает таким образом. Он по-прежнему загружает ответ в память, прежде чем сохранить его в файл.
ОБНОВИТЬ
Если вам нужен маленький клиент (Python 2.x /3.x), который может загружать большие файлы с FTP, вы можете найти его здесь . Он поддерживает многопоточность и повторное соединение (он контролирует соединения), а также настраивает параметры сокета для задачи загрузки.
источник
chunk_size
имеет решающее значение. по умолчанию это 1 (1 байт). это означает, что для 1 МБ это будет 1 миллион итераций. docs.python-requests.org/en/latest/api/…f.flush()
кажется ненужным Что вы пытаетесь достичь с помощью этого? (использование вашей памяти не будет 1,5 ГБ, если вы уроните ее).f.write(b'')
(ifiter_content()
может вернуть пустую строку) должен быть безвредным и, следовательно,if chunk
может быть также отброшен.f.flush()
не сбрасывает данные на физический диск. Он передает данные в ОС. Обычно этого достаточно, если не происходит сбоя питания.f.flush()
делает код медленнее здесь без причины. Сброс происходит, когда соответствующий файловый буфер (внутри приложения) заполнен. Если вам нужны более частые записи; передать параметр buf.size вopen()
.r.close()
Это намного проще, если вы используете
Response.raw
иshutil.copyfileobj()
:Это потоковое файл на диск без использования чрезмерной памяти, и код прост.
источник
with
блок для выполнения запроса:with requests.get(url, stream=True) as r:
with requests.get()
была объединена только 2017-06-07! Ваше предложение разумно для людей, у которых есть запросы 2.18.0 или более поздние. Ссылка: github.com/requests/requests/issues/4136read
метод:response.raw.read = functools.partial(response.raw.read, decode_content=True)
Не совсем то, о чем спрашивал OP, но ... это до смешного легко сделать с помощью
urllib
:Или так, если вы хотите сохранить его во временный файл:
Я наблюдал за процессом:
И я увидел, что файл растет, но использование памяти осталось на 17 МБ. Я что-то пропустил?
источник
from urllib import urlretrieve
shutil.copyfileobj
с наибольшим количеством голосов, см. мои и другие комментарии тамВаш размер куска может быть слишком большим, вы пытались сбросить его - может быть, 1024 байта за раз? (также вы можете использовать,
with
чтобы привести в порядок синтаксис)Кстати, как вы делаете вывод, что ответ был загружен в память?
Звучит так, как будто python не сбрасывает данные в файл, из других вопросов SO, которые вы могли бы попробовать
f.flush()
иos.fsync()
заставить файл записать и освободить память;источник
f.flush(); os.fsync()
может заставить запись освободить память.os.fsync(f.fileno())
def DownloadFile(url)