У меня есть менеджер API, который подключается к URL-адресу и захватывает некоторые json. Очень просто. Вырезать из метода:urlopen зависает в случайном порядке, timout игнорируется
req = Request(url)
socket.setdefaulttimeout(timeout)
resp = urlopen(req, None, timeout)
data = resp.read()
resp.close()
Это отлично работает большую часть времени, но через случайные промежутки времени она занимает 5 секунд, чтобы выполнить запрос. Даже когда таймаут установлен на 0,5 или 1,0 или что-то еще. Я зарегистрировал его очень близко, поэтому я на 100% уверен, что строка, которая занимает время, занимает номер # 3 (т.е. resp = urlopen (req, None, timeout)).
Ive пытался все решения Ive найденные по теме тайм-аута декораторов и таймерами и т.д. (Для того, чтобы перечислить некоторые из них: Python urllib2.urlopen freezes script infinitely even though timeout is set, How can I force urllib2 to time out?, Timing out urllib2 urlopen operation in Python 2.4, Timeout function if it takes too long to finish )
Но ничего работает. Мое впечатление, что нить зависает, а urlopen что-то делает, и когда это делается, он размораживается, а затем все таймеры и таймауты возвращают ошибки таймаута. но время выполнения еще больше 5 секунд.
Я нашел this старый список рассылки относительно urllib2 и обработки закодированного кодирования. Поэтому, если проблема все еще присутствует, то решением может быть написать пользовательский urlopen на основе httplib.HTTP, а не httplib.HTTPConnection. Другим возможным решением является попытка использования многопоточной магии.
Оба решения кажутся агрессивными. И мне кажется, что тайм-аут не работает полностью.
Очень важно, чтобы время выполнения сценария не превышало 0,5 с. Кто знает, почему я испытываю зависания или, может быть, способ помочь мне?
Обновление, основано на принятом ответе: Я изменил подход и вместо этого использовал curl. Together w unix timeout работает так, как я хочу. Пример следующий код:
t_timeout = str(API_TIMEOUT_TIME)
c_timeout = str(CURL_TIMEOUT_TIME)
cmd = ['timeout', t_timeout, 'curl', '--max-time', c_timeout, url]
prc = Popen(cmd, stdout=PIPE, stderr=PIPE)
response = prc.communicate()
Поскольку curl принимает только int как таймаут, я добавил таймаут. таймаут принимает поплавки.
Отличный ответ. Спасибо. Даже если я чувствую, что должен быть общий тайм-аут. Ill update, если я реализую пользовательский HTTP-клиент, как было предложено. – user2520443