Timeout für urllib2.urlopen () in pre Python 2.6 Versionen
Frage
Die urllib2 Dokumentation sagt, dass timeout Parameter hinzugefügt wurde in Python 2.6. Leider 2.5 meine Code-Basis auf Python wurde ausgeführt und 2.4-Plattformen.
Gibt es eine andere Möglichkeit, den Timeout zu simulieren? Alles, was ich tun möchte, ist damit der Code den Remote-Server für eine bestimmte Zeit sprechen.
Vielleicht eine Alternative Bibliothek-in gebaut? (Nicht will, 3rd-Party installieren, wie pycurl)
Lösung
Sie eine globale Timeout für alle Socket-Operationen (einschließlich HTTP-Anfragen) eingestellt kann mit:
wie folgt aus:
import urllib2
import socket
socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/')
in diesem Fall Ihre urllib2 Anfrage würde nach 30 Sekunden Timeout und eine Socket-Ausnahme aus.
(dies wurde in Python 2.3 hinzugefügt)Andere Tipps
Mit erheblichen Irritationen, können Sie die httplib.HTTPConnection Klasse überschreiben, dass die urllib2.HTTPHandler Anwendungen.
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)
Ich denke, die beste Wahl zu Patch ist (oder eine lokale Version bereitstellen) Ihr urllib2 mit der Wechsel von dem 2.6 Wartung Zweig
Die Datei in /usr/lib/python2.4/urllib2.py
(auf Linux und 2.4) sollte
Ich verwende httplib aus der Standardbibliothek. Es hat eine tote einfache API, aber nur Griffe http wie Sie sich vorstellen können. IIUC urllib httplib verwendet die HTTP Sachen zu implementieren.
Sie müssen an zwei Stellen festgelegt Timeout.
import urllib2
import socket
socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/', timeout=30)
Nun, die Art und Weise Timeout wird in beide 2.4 behandelt oder 2.6 ist das gleiche. Wenn Sie die Datei urllib2.py in 2.6 öffnen u würde sehen, dass es ein zusätzliches Argument als Timeout und Griffe nimmt es die socket.defaulttimeout () Methode verwendet wird, wie erwähnt ist die Antwort 1.
So was Sie wirklich brauchen nicht aktualisieren Sie Ihre urllib2.py in diesem Fall.