Domanda

Il urllib2 documentazione dice che timeout parametro è stato aggiunto in Python 2.6. Purtroppo la mia base di codice è stato in esecuzione su Python 2.5 e 2.4 piattaforme.

C'è un modo alternativo per simulare il timeout? Tutto quello che voglio fare è consentire il codice per parlare il server remoto per un importo fisso di tempo.

Forse qualsiasi alternativa libreria incorporata? (Non vuoi installare 3a parte, come pycurl)

È stato utile?

Soluzione

è possibile impostare un timeout globale per tutte le operazioni di socket (comprese le richieste HTTP) utilizzando:

socket.setdefaulttimeout()

in questo modo:

import urllib2
import socket
socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/')

In questo caso, la richiesta sarebbe urllib2 timeout dopo 30 secondi e un'eccezione di socket. (Questo è stato aggiunto in Python 2.3)

Altri suggerimenti

Con notevole irritazione, è possibile sostituire la classe httplib.HTTPConnection che l'urllib2.HTTPHandler utilizza.

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)

Credo che la scelta migliore è quella di patch (o di distribuire una versione locale del) la tua urllib2 con il cambiamento dal ramo 2.6 di manutenzione

Il file dovrebbe essere in /usr/lib/python2.4/urllib2.py (su Linux e 2.4)

Io uso httplib dalla libreria standard. Ha una semplice API morto, ma gestisce solo http come è facile intuire. IIUC urllib utilizza httplib per implementare la roba http.

È necessario impostare timeout in due punti.

import urllib2
import socket

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

Bene, il modo in cui timeout è gestita sia in 2.4 o 2.6 è lo stesso. Se si apre il file in urllib2.py 2.6 u sarebbe vedere che prende un argomento extra come timeout e lo gestisce con il metodo socket.defaulttimeout () come detto è la risposta 1.

Così davvero non è necessario aggiornare l'urllib2.py in questo caso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top