我正在制作一个python URL抓取程序。为了我的目的,我希望它真的很快超时,所以我正在做
urllib2.urlopen("http://.../", timeout=2)
当然它应该正确地超时。但是,它并不打算关闭与服务器的连接,因此服务器认为客户端仍然连接。如何让urllib2在超时后关闭连接?
运行gc.collect()不起作用,如果我无法帮助它,我不想使用httplib。
我能得到的最接近的是:第一次尝试会超时。服务器报告连接关闭只是,因为第二次尝试超时。然后,服务器报告连接关闭只是,因为第三次尝试超时。无限无限。
非常感谢。
答案 0 :(得分:2)
我怀疑套接字在堆栈帧中是否仍处于打开状态。当Python引发异常时,它会存储堆栈帧,因此调试器和其他工具可以查看堆栈和内省值。
由于历史原因,现在为了向后兼容性,堆栈信息(在每个线程的基础上)存储在sys中(请参阅sys.exc_info(),sys.exc_type和其他)。这是Python 3.0中已删除的内容之一。
这对你来说意味着堆栈仍然存在并被引用。堆栈包含一些具有打开套接字的函数的本地数据。这就是套接字尚未关闭的原因。只有当移除堆栈跟踪时,才会对所有内容进行gc'ed。
要测试是否是这种情况,请插入类似
的内容try:
1/0
except ZeroDivisionError:
pass
你的except子句中的。这是用其他东西替换当前异常的快速方法。
答案 1 :(得分: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
任何人都有更好的方法吗?