urllib2超时但不关闭套接字连接
问题描述:
我正在制作一个python URL抓取程序。对于我而言,我希望它真的快超时,所以我超时正确的,因为它应该做urllib2超时但不关闭套接字连接
urllib2.urlopen("http://.../", timeout=2)
当然。但是,它不打扰关闭到服务器的连接,所以服务器认为客户端仍然连接。如何让urllib2在超时后关闭连接?
运行gc.collect()不起作用,如果我无法帮助,我不想使用httplib。
我能得到的最接近的是:第一次尝试会超时。服务器报告连接关闭只是作为第二次尝试超时。然后,服务器报告连接关闭只是作为第三次尝试超时。无限广告。
非常感谢。
答
我怀疑套接字仍然在栈帧中打开。当Python引发异常时,它会存储堆栈帧,以便调试器和其他工具可以查看堆栈并反省值。由于历史原因,现在为了向后兼容,堆栈信息在sys(参见sys.exc_info(),sys.exc_type和其他)中存储(以每个线程为基础)。这是Python 3.0中已被删除的内容之一。
这对你意味着什么是堆栈还活着,并引用。这个栈包含了一些具有开放套接字的函数的本地数据。这就是套接字尚未关闭的原因。只有当堆栈跟踪被移除时,所有内容才会被删除。
为了测试是否是这样的情况下,插入类似
try:
1/0
except ZeroDivisionError:
pass
在except从句。这是用其他方法替换当前异常的快速方法。
答
这是一个黑客,但下面的代码工程。如果请求在另一个函数中,并且它不引发异常,那么套接字始终关闭。
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
是否有人有更好的方法?
嗯!一个非常有趣的想法。谢谢,但它不工作;不过,我从来没有这样想过。 我认为对于我的项目来说,我的整个推理只是有点太过分。对我而言,最好不要依赖于此,而只是终止服务器上的重复连接。 – Michael 2010-01-26 06:19:21