Python 2.6之前版本中urllib2.urlopen()的超时设置

29 投票
6 回答
22286 浏览
提问于 2025-04-15 18:08

urllib2的文档提到,timeout这个参数是在Python 2.6版本中新增的。可惜的是,我的代码现在还在使用Python 2.5和2.4的环境。

有没有其他方法可以模拟超时的功能呢?我只是想让代码和远程服务器交流一个固定的时间。

有没有什么内置的替代库?(我不想安装第三方库,比如pycurl)

6 个回答

2

我觉得你最好的选择是对你的urllib2进行修补(或者使用一个本地版本),可以参考2.6维护分支中的更改

这个文件应该在 /usr/lib/python2.4/urllib2.py 这个路径下(在Linux系统和Python 2.4版本中)。

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

你可以为所有的套接字操作(包括HTTP请求)设置一个全局的超时时间,方法是使用:

socket.setdefaulttimeout()

用法如下:

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

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

撰写回答