28 votes

délai d'expiration pour urllib2.urlopen () dans les versions antérieures à Python 2.6

La documentation urllib2 indique que le paramètre timeout a été ajouté dans Python 2.6. Malheureusement, ma base de code a fonctionné sur les plates-formes Python 2.5 et 2.4.

Existe-t-il un autre moyen de simuler le délai d'expiration? Tout ce que je veux faire, c'est autoriser le code à parler au serveur distant pendant une durée fixe.

Peut-être une autre bibliothèque intégrée? (Je ne veux pas installer un tiers, comme pycurl)

57voto

Corey Goldberg Points 15625

vous pouvez définir un délai d'expiration global pour toutes les opérations de socket (y compris les requêtes HTTP) en utilisant:

socket.setdefaulttimeout()

comme ça:

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

dans ce cas, votre demande urllib2 expirerait après 30 secondes et lèverait une exception de socket. (cela a été ajouté dans Python 2.3)

4voto

Philip Z Points 156

Avec une irritation considérable, vous pouvez remplacer la classe httplib.HTTPConnection utilisée par 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)
 

2voto

Kimvais Points 12453

Je pense que votre meilleur choix est de patcher (ou de déployer une version locale de) votre urllib2 avec le changement de la branche de maintenance 2.6

Le fichier doit être en /usr/lib/python2.4/urllib2.py (sous linux et 2.4)

1voto

Kris Walker Points 433

J'utilise httplib de la bibliothèque standard. Il a une API simple et morte, mais ne gère que http comme vous pouvez le deviner. IIUC urllib utilise httplib pour implémenter le contenu http.

1voto

Daniel Magnusson Points 2945

Vous devez définir un délai d'expiration à deux endroits.

 import urllib2
import socket

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X