Подтвердить что ты не робот

Как повторить попытку urllib2.request при сбое?

Когда urllib2.request достигает таймаута, возникает исключение urllib2.URLError. Что такое pythonic способ повторного установления соединения?

4b9b3361

Ответ 1

Я бы использовал декоратор retry. Есть и другие, но это работает очень хорошо. Вот как вы можете его использовать:

@retry(urllib2.URLError, tries=4, delay=3, backoff=2)
def urlopen_with_retry():
    return urllib2.urlopen("http://example.com")

Это повторит функцию, если URLError поднят. Проверьте ссылку выше для документации по параметрам, но в основном она будет повторять максимум 4 раза, при этом экспоненциальная задержка отсрочки удваивается каждый раз, например. 3 секунды, 6 секунд, 12 секунд.

Ответ 2

Есть несколько библиотек, которые специализируются на этом.

Один backoff, который разработан с особенно функциональной чувствительностью. Декораторам передаются произвольные вызывающие обратные генераторы, которые дают последовательные значения задержки. Простая экспоненциальная отсрочка с максимальным временем повторения 32 секунд может быть определена как:

@backoff.on_exception(backoff.expo,
                      urllib2.URLError,
                      max_value=32)
def url_open(url):
    return urllib2.urlopen("http://example.com")

Другим является retrying, который имеет очень похожую функциональность, но API, где параметры повтора задаются с помощью предопределенных ключевых слов.

Ответ 3

Чтобы повторить попытку с тайм-аутом, вы можете поймать исключение в качестве @Karl Barker в комментарии:

assert ntries >= 1
for _ in range(ntries):
    try:
        page = urlopen(request, timeout=timeout)
        break # success
    except URLError as err:
        if not isinstance(err.reason, socket.timeout):
           raise # propagate non-timeout errors
else: # all ntries failed 
    raise err # re-raise the last timeout error
# use page here