29

urllib2 文档超时参数是在 Python 2.6 中添加的。不幸的是,我的代码库一直在 Python 2.5 和 2.4 平台上运行。

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

也许任何替代的内置库?(不想安装第 3 方,如 pycurl)

4

6 回答 6

58

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

socket.setdefaulttimeout()

像这样:

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

在这种情况下,您的 urllib2 请求将在 30 秒后超时并引发套接字异常。(这是在 Python 2.3 中添加的)

于 2010-01-18T14:19:07.650 回答
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)
于 2012-03-29T01:41:37.203 回答
2

I think your best choice is to patch (or deploy an local version of) your urllib2 with the change from the 2.6 maintenance branch

The file should be in /usr/lib/python2.4/urllib2.py (on linux and 2.4)

于 2010-01-18T09:13:04.287 回答
1

You must set timeout in two places.

import urllib2
import socket

socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/', timeout=30)
于 2012-04-17T08:57:59.503 回答
1

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

于 2010-01-18T09:19:05.130 回答
0

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

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

于 2011-03-30T05:13:55.507 回答