2010-01-18 9 views
28

Die urllib2 documentation sagt, dass Timeout Parameter in Python 2.6 hinzugefügt wurde. Leider läuft meine Codebasis auf Python 2.5 und 2.4 Plattformen.Timeout für urllib2.urlopen() in vor Python 2.6-Versionen

Gibt es alternative Möglichkeiten, das Timeout zu simulieren? Ich möchte nur zulassen, dass der Code den Remote-Server für eine bestimmte Zeit spricht.

Vielleicht eine alternative integrierte Bibliothek? (Ich will nicht 3rd-Party installieren, wie pycurl)

Antwort

57

Sie eine globale Timeout für alle Socket-Operationen (einschließlich HTTP-Anfragen) einstellen, indem Sie:

socket.setdefaulttimeout()

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 Timeout nach 30 Sekunden und wirf eine Socket-Ausnahme. (Dies wurde in Python 2.3 hinzugefügt)

+0

'Das Modul Urllib2 wurde auf mehrere Module in Python 3.0 namens urllib.request und urllib.error aufgeteilt Die Restcodes sind einfach genug. – MewX

2

Ich denke, die beste Wahl zu Patch ist (oder eine lokale Version bereitstellen) Ihr urllib2 mit the change from the 2.6 maintenance branch

Die Datei in /usr/lib/python2.4/urllib2.py (auf Linux sein sollte und 2.4)

+1

Was ist mit socket.settimeout()? Wird es helfen? – rubayeet

+0

Ich denke es könnte, ich hatte das gleiche Problem vor einiger Zeit, und aus irgendeinem Grund konnte ich es nicht zum Laufen bringen. Ich habe jedoch keine Erinnerung wo der Code sein könnte, kann nicht überprüfen:/ – Kimvais

1

Ich benutze httplib aus der Standardbibliothek. Es hat eine tote einfache API, aber behandelt nur http, wie Sie vermuten könnten. IIUU urlib verwendet httplib, um das http-Zeug zu implementieren.

+2

Leider unterstützt httplib Timeout nur in 2.6 – rubayeet

0

Nun, die Art und Weise wie Timeout in 2.4 oder 2.6 behandelt wird, ist das gleiche. Wenn Sie die Datei urllib2.py in 2.6 öffnen, sehen Sie, dass es ein zusätzliches Argument als Timeout benötigt und es mit der socket.defaulttimeout() -Methode behandelt, wie erwähnt ist die Antwort 1.

Sie brauchen also Ihr urllib2 wirklich nicht zu aktualisieren .py in diesem Fall.

4

Mit beträchtlicher Irritation können Sie die Klasse httplib.HTTPConnection überschreiben, die der urllib2.HTTPHandler verwendet.

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) 
1

Sie müssen die Zeitüberschreitung an zwei Stellen einstellen.

import urllib2 
import socket 

socket.setdefaulttimeout(30) 
f = urllib2.urlopen('http://www.python.org/', timeout=30) 
+2

Beide arbeiten unabhängig voneinander. Timeout = 30 funktioniert jedoch von alleine. Das war die beste Antwort für mich, also entfernte ich die -1, die du hattest. Wenn Sie den Titel Ihrer Antwort auf etwas "Sie können das Timeout an einem oder beiden Orten einstellen" ändern. Auch die Hauptfrage befasst sich mit dem Problem der Python-Version. – ruralcoder

Verwandte Themen