5 лет спустя, но, надеюсь, это поможет кому-то еще ...
Я ломал свой мозг, пытаясь понять это. Моя проблема заключалась в том, что сервер возвращал поврежденный контент и, таким образом, возвращал меньше данных, чем предполагалось.
Я придумала неприятное решение, которое, кажется, работает правильно. Вот оно:
# NOTE I directly disabling blocking is not necessary but it represents
# an important piece to the problem so I am leaving it here.
# http_response.fp._sock.socket.setblocking(0)
http_response.fp._sock.settimeout(read_timeout)
http_response.read(chunk_size)
ПРИМЕЧАНИЕ Это решение также работает для , когда Python запрашивает ANY библиотеку, которая реализует обычные сокеты Python (какими должны быть все они?) Вам просто нужно пройти несколько уровней глубже:
resp.raw._fp.fp._sock.socket.setblocking()
resp.raw._fp.fp._sock.settimeout(read_timeout)
resp.raw.read(chunk_size)
На момент написания этой статьи я не пробовал следующее, но теоретически это должно работать:
resp = requests.get(some_url, stream=True)
resp.raw._fp.fp._sock.socket.setblocking()
resp.raw._fp.fp._sock.settimeout(read_timeout)
for chunk in resp.iter_content(chunk_size):
# do stuff
Объяснение
Я наткнулся на этот подход при чтении этого SO вопроса для установки времени ожидания для socket.recv
В конце дня любой http-запрос имеет сокет. Для httplib этот сокет находится на resp.raw._fp.fp._sock.socket
. resp.raw._fp.fp._sock
- это socket._fileobj
(который я, честно говоря, не слишком глубоко изучил), и я полагаю, что метод settimeout
внутренне устанавливает его для атрибута socket
.