установить тайм-аут на метод чтения ответа http в python - PullRequest
1 голос
/ 04 апреля 2010

Я создаю менеджер загрузок в python для развлечения, и иногда соединение с сервером все еще включено, но сервер не отправляет мне данные, поэтому метод чтения (HTTPResponse) блокирует меня навсегда. Это происходит, например, при загрузке с сервера, расположенного за пределами моей страны, который ограничивает пропускную способность для других стран.

Как установить тайм-аут для метода чтения (например, 2 минуты)?

Спасибо, Нир.

Ответы [ 4 ]

3 голосов
/ 04 апреля 2010

Если вы застряли на какой-то версии Python < 2.6, один (несовершенный, но пригодный для использования) подход - сделать

import socket
socket.setdefaulttimeout(10.0)  # or whatever

перед началом использования httplib. Документы: здесь , и четко указано, что * Python 2.3 доступен setdefaulttimeout - каждый сокет, созданный с момента выполнения этого вызова до момента повторного вызова той же функции, будет использовать этот тайм-аут 10 секунд. Вы можете использовать getdefaulttimeout перед установкой нового тайм-аута, если вы хотите сохранить предыдущий тайм-аут (включая нулевой), чтобы вы могли восстановить его позже (с другим setdefaulttimeout).

Эти функции и идиомы весьма полезны, когда вам нужно использовать более старую высокоуровневую библиотеку, которая использует Python socket s, но не дает хорошего способа установить тайм-ауты (конечно, лучше использовать обновленные выше- библиотеки уровней, например, версия httplib, которая поставляется с 2.6 или сторонняя версия httplib2 в этом случае, но это не всегда возможно, и игра с настройкой тайм-аута по умолчанию может быть хорошим обходным путем).

2 голосов
/ 04 апреля 2010

Вы должны установить его во время HTTPConnection инициализации.

Примечание: если вы используете более старую версию Python, вы можете установить httplib2 ; Многие считают его лучшей альтернативой httplib и поддерживают timeout .
Я никогда не использовал это, и я только сообщаю, что говорят документация и блоги.

1 голос
/ 30 августа 2010

Установка тайм-аута по умолчанию может прервать загрузку рано, если она велика, в отличие от прерывания, только если он прекращает получать данные для значения тайм-аута. HTTPlib2 - это, вероятно, верный путь.

0 голосов
/ 03 декабря 2015

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.

...