Сообщить об ошибке.

Загрузка больших данных модулем requests в Python

Потоковая отправка/загрузка контента модулем requests

Содержание:


Управление процессом загрузки контента с сервера.

По умолчанию, когда отправляется запрос на сервер, тело ответа загружается немедленно. Можно переопределить такое поведение и отложить загрузку тела ответа сервера до тех пор, пока библиотека requests не получит доступ к атрибуту Response.content, который управляется аргументом stream, передаваемый при создании запроса.

tarball_url = 'https://github.com/psf/requests/tarball/master'
resp = requests.get(tarball_url, stream=True)

На данный момент загружены только заголовки ответов, и соединение остается открытым, что позволяет сделать загрузку нужного контента условным:

if int(resp.headers['content-length']) < TOO_LONG:
  content = resp.content
  ...

Можно дополнительно управлять рабочим процессом с помощью методов Response.iter_content() и Response.iter_lines(). Кроме того, можно прочитать не декодированное тело ответа сервера, которое возвращает атрибут Response.raw (из базового urllib3.HTTPResponse).

Если установить для аргумента потока stream значение True при подготовке запроса или при его выполнении методом requests.get(), requests.post() и т.д., то библиотека не сможет освободить соединение обратно в пул, если клиент не прочитает все данные или не вызовет метод Response.close(). Это может привести к неэффективности подключений.

Если при использовании stream=True обнаружится, что тело запроса нужно прочитать частично (или вообще не надо читать), то запрос к серверу следует делать в контекстном менеджере with, чтобы он всегда смог автоматически закрыться:

with requests.get('https://httpbin.org/get', stream=True) as resp:
    # здесь делаем что-нибудь с ответом.

Потоковая передача данных для исходящих/входящих запросов.

Библиотека requests поддерживают потоковую отправку/загрузку контента, которая позволяет отправлять/загружать большие потоки или файлы, не считывая их в память целиком.

Для потоковой передачи или загрузки просто предоставьте файлоподобный объект для тела запроса:

Пример отправки большого файла:

with open('massive-body', 'rb') as fp:
    requests.post('http://some.url/streamed', data=fp)

Предупреждение. Настоятельно рекомендуется открывать файлы в двоичном режиме 'rb'. Это связано с тем, что запросы могут попытаться предоставить заголовок Content-Length, и если это произойдет, то это значение будет установлено на количество байтов в файле. При открытии файла в текстовом режиме могут возникнуть ошибки.

Передача данных частями для исходящих/входящих запросов.

Библиотека requests также поддерживает фрагментированную передачу контента для исходящих и входящих запросов. Чтобы отправить запрос с фрагментом тела запроса, просто предоставьте генератор (или любой итератор без указания длины) для тела запроса:

def gen():
    yield 'hi'
    yield 'there'

requests.post('http://some.url/chunked', data=gen())

Для фрагментированных закодированных ответов лучше всего перебирать данные с помощью Response.iter_content(). В идеальной ситуации нужно установить для запроса аргумент stream=True, и в этом случае можно выполнять итерацию по частям, вызывая метод .iter_content() с аргументом chunk_size=None . Если нужно установить максимальный размер блока, то можно установить параметр chunk_size в любое целое число.

Поддержка соединения при больших объемах данных.

Благодаря urllib3 поддержка соединения keep-alive работает на 100% автоматически в течение всего сеанса! Любые запросы, которые делаются в течение сеанса, автоматически повторно используют соответствующее соединение!

Обратите внимание, что соединения освобождаются обратно в пул для повторного использования только после того, как все данные тела были прочитаны. Обязательно установите stream=False или прочитайте до конца контент, находящийся в Response.content.