2010-01-26 58 views
0

我正在制作一个python URL抓取程序。对于我而言,我希望它真的快超时,所以我超时正确的,因为它应该做urllib2超时但不关闭套接字连接

urllib2.urlopen("http://.../", timeout=2)

当然。但是,它不打扰关闭到服务器的连接,所以服务器认为客户端仍然连接。如何让urllib2在超时后关闭连接?

运行gc.collect()不起作用,如果我无法帮助,我不想使用httplib。

我能得到的最接近的是:第一次尝试会超时。服务器报告连接关闭只是作为第二次尝试超时。然后,服务器报告连接关闭只是作为第三次尝试超时。无限广告。

非常感谢。

回答

2

我怀疑套接字仍然在栈帧中打开。当Python引发异常时,它会存储堆栈帧,以便调试器和其他工具可以查看堆栈并反省值。由于历史原因,现在为了向后兼容,堆栈信息在sys(参见sys.exc_info(),sys.exc_type和其他)中存储(以每个线程为基础)。这是Python 3.0中已被删除的内容之一。

这对你意味着什么是堆栈还活着,并引用。这个栈包含了一些具有开放套接字的函数的本地数据。这就是套接字尚未关闭的原因。只有当堆栈跟踪被移除时,所有内容才会被删除。

为了测试是否是这样的情况下,插入类似

try: 
    1/0 
except ZeroDivisionError: 
    pass 

在except从句。这是用其他方法替换当前异常的快速方法。

+0

嗯!一个非常有趣的想法。谢谢,但它不工作;不过,我从来没有这样想过。 我认为对于我的项目来说,我的整个推理只是有点太过分。对我而言,最好不要依赖于此,而只是终止服务器上的重复连接。 – Michael 2010-01-26 06:19:21

0

这是一个黑客,但下面的代码工程。如果请求在另一个函数中,并且它不引发异常,那么套接字始终关闭。

def _fetch(self, url): 
    try: 
     return urllib2.urlopen(urllib2.Request(url), timeout=5).read() 
    except urllib2.URLError, e: 
     if isinstance(e.reason, socket.timeout): 
      return None 
     else: 
      raise e 

def fetch(self, url): 
    x = None 
    while x is None: 
     x = self._fetch(url) 
     print "Timeout" 
    return x 

是否有人有更好的方法?