Когда urllib2.request
достигает таймаута, возникает исключение urllib2.URLError
.
Что такое pythonic способ повторного установления соединения?
Как повторить попытку urllib2.request при сбое?
Ответ 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