Таймаут для urllib2.urlopen() в версиях pre Python 2.6
документация urllib2 говорит, что параметр тайм-аута был добавлен в Python 2.6. К сожалению, моя база кода работает на платформах Python 2.5 и 2.4.
Есть ли альтернативный способ моделирования таймаута? Все, что я хочу сделать, это разрешить коду говорить на удаленном сервере в течение определенного времени.
Возможно, любая альтернативная встроенная библиотека? (Не хотите устанавливать стороннего участника, например pycurl)
Ответы
Ответ 1
вы можете установить глобальный тайм-аут для всех операций сокета (включая HTTP-запросы), используя:
socket.setdefaulttimeout()
вот так:
import urllib2
import socket
socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/')
в этом случае ваш запрос urllib2 будет истекать через 30 секунд и вызывать исключение сокета. (это было добавлено в Python 2.3)
Ответ 2
Со значительным раздражением вы можете переопределить класс httplib.HTTPConnection, который использует urllib2.HTTPHandler.
def urlopen_with_timeout(url, data=None, timeout=None):
# Create these two helper classes fresh each time, since
# timeout needs to be in the closure.
class TimeoutHTTPConnection(httplib.HTTPConnection):
def connect(self):
"""Connect to the host and port specified in __init__."""
msg = "getaddrinfo returns an empty list"
for res in socket.getaddrinfo(self.host, self.port, 0,
socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
self.sock = socket.socket(af, socktype, proto)
if timeout is not None:
self.sock.settimeout(timeout)
if self.debuglevel > 0:
print "connect: (%s, %s)" % (self.host, self.port)
self.sock.connect(sa)
except socket.error, msg:
if self.debuglevel > 0:
print 'connect fail:', (self.host, self.port)
if self.sock:
self.sock.close()
self.sock = None
continue
break
if not self.sock:
raise socket.error, msg
class TimeoutHTTPHandler(urllib2.HTTPHandler):
http_request = urllib2.AbstractHTTPHandler.do_request_
def http_open(self, req):
return self.do_open(TimeoutHTTPConnection, req)
opener = urllib2.build_opener(TimeoutHTTPHandler)
opener.open(url, data)
Ответ 3
Я думаю, что ваш лучший выбор - запланировать (или развернуть локальную версию) ваш urllib2 с изменение из ветки обслуживания 2.6
Файл должен находиться в /usr/lib/python2.4/urllib2.py
(на linux и 2.4)
Ответ 4
Я использую httplib из стандартной библиотеки. У этого есть мертвый простой API, но только обрабатывает http, как Вы могли догадаться. IIUC urllib использует httplib для реализации http-материала.
Ответ 5
Вы должны установить тайм-аут в двух местах.
import urllib2
import socket
socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/', timeout=30)
Ответ 6
Ну, то, как тайм-аут обрабатывается либо в 2,4, либо в 2.6, то же самое. Если вы откроете файл urllib2.py в 2.6, вы увидите, что он принимает дополнительный аргумент как тайм-аут и обрабатывает его с помощью метода socket.defaulttimeout(), как упоминалось, это ответ 1.
Поэтому вам не нужно обновлять urllib2.py в этом случае.