在Python 2.6之前的版本中,urllib2.urlopen()的超时

时间:2010-01-18 08:49:58

标签: python urllib2 urlopen

urllib2 documentation表示在Python 2.6中添加了 timeout 参数。不幸的是,我的代码库已经在Python 2.5和2.4平台上运行。

有没有其他方法可以模拟超时?我想做的就是让代码在一段固定的时间内与远程服务器通话。

也许任何替代内置库? (不要像pycurl那样安装第三方)

6 个答案:

答案 0 :(得分:57)

您可以使用以下命令为所有套接字操作(包括HTTP请求)设置全局超时:

socket.setdefaulttimeout()

像这样:

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

在这种情况下,你的urllib2请求会在30秒后超时并抛出套接字异常。 (这是在Python 2.3中添加的)

答案 1 :(得分:4)

有很大的烦恼,你可以覆盖urllib2.HTTPHandler使用的httplib.HTTPConnection类。

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)

答案 2 :(得分:2)

我认为您最好的选择是使用the change from the 2.6 maintenance branch修补(或部署本地版本)urllib2

该文件应该在/usr/lib/python2.4/urllib2.py(在linux和2.4上)

答案 3 :(得分:1)

我使用标准库中的httplib。它有一个死的简单API,但只能处理你可能猜到的http。 IIUC urllib使用httplib来实现http内容。

答案 4 :(得分:1)

您必须在两个地方设置超时。

import urllib2
import socket

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

答案 5 :(得分:0)

嗯,在2.4或2.6中处理超时的方式是相同的。如果你在2.6中打开urllib2.py文件,你会看到它需要额外的参数作为超时,并使用socket.defaulttimeout()方法处理它,如上所述是答案1。

所以你真的不需要在这种情况下更新你的urllib2.py。