Избегание ChunkedEncodingError для пустой части с запросами 2.3.0
Я использую Запросы для загрузки файла (несколько гигабайт) с сервера. Чтобы обеспечить обновления хода выполнения (и чтобы весь файл не мог быть сохранен в памяти), я установил stream=True
и написал загрузку в файл:
with open('output', 'w') as f:
response = requests.get(url, stream=True)
if not response.ok:
print 'There was an error'
exit()
for block in response.iter_content(1024 * 100):
f.write(block)
completed_bytes += len(block)
write_progress(completed_bytes, total_bytes)
Однако в какой-то случайной точке загрузки Requests выбрасывает ChunkedEncodingError
. Я попал в источник и обнаружил, что соответствует исключению IncompleteRead
. Я вставил оператор журнала вокруг этих строк и обнаружил, что e.partial = "\r"
. Я знаю, что сервер придает загрузке низкий приоритет, и я подозреваю, что это исключение возникает, когда сервер слишком долго ждет отправки следующего фрагмента.
Как и ожидалось, исключение останавливает загрузку. К сожалению, сервер не реализует диапазоны контента HTTP/1.1, поэтому я не могу просто возобновить его. Я играл с увеличением внутреннего тайм-аута urllib3, но исключение все еще сохраняется.
В любом случае, чтобы сделать основной urllib3 (или Requests) более терпимым к этим пустым (или более поздним) фрагментам, чтобы файл мог полностью загрузить?
Ответы
Ответ 1
import httplib
def patch_http_response_read(func):
def inner(*args):
try:
return func(*args)
except httplib.IncompleteRead, e:
return e.partial
return inner
httplib.HTTPResponse.read = patch_http_response_read(httplib.HTTPResponse.read)
Я не могу воспроизвести вашу проблему прямо сейчас, но я думаю, что это может быть патч. Это позволяет вам работать с дефектными серверами http.
Большинство плохих серверов передают все данные, но из-за ошибок реализации они неправильно закрывают сессию и httplib повышают ошибку и хоронят ваши драгоценные байты.