这是一个两部分问题。第一个是如何正确关闭与urllib2的连接?我已经看到了很多例子,我采用了我能找到的最佳解决方案。但是,关闭文件似乎存在问题。
目前我使用contextlib的closing()如下:
try:
with closing(self.opener.open(self.address,
None,
self.timeout)) as page:
self.data = page.read()
except:
# bail out..
但是,在OSX上很长一段时间后,我仍然会收到“太多打开的文件”错误。我使用ulimit将文件增加到2000及以上。我还将内核的max文件设置为> 40,000。我应该注意,这个方法所在的对象没有被处理掉,并且它在程序的生命周期内保持不变。但是,我只保留对象中存储的“数据”以及地址和超时。我没有保存文件类对象。我认为问题可能是引用,但我不相信,因为我从不直接存储对类文件对象的引用,只存储read()中的数据。每次线程从队列中拉出url时,都会重复使用这些对象并重新加载新数据。
我一次只打开大约50个连接。我不太明白我怎么会用完文件。此外,当我用完文件时,netstat开始出现malloc错误:
netstat(439) malloc: *** mmap(size=18446744073708605440) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
netstat: malloc 18446744073708605396 bytes: Cannot allocate memory
我也找不到重置连接的方法,并且在不关闭的情况下让netstat恢复正常。
netstat -m
$ netstat -m
475/3803 mbufs in use:
475 mbufs allocated to data
3328 mbufs allocated to caches
407/3814 mbuf 2KB clusters in use
0/577 mbuf 4KB clusters in use
0/12 mbuf 16KB clusters in use
11242 KB allocated to network (8.3% in use)
0 requests for memory denied
0 requests for memory delayed
0 calls to drain routines
我无法找到错误,但我认为连接没有及时关闭,我很清楚连接即使连接到单个域也不会被重用(我希望如此)。这是问题的第二部分。有人如何重用与urllib2的连接?
我有多个线程从队列中获取URL并且每个线程都通过这种例程检索数据。如果可能的话,我想重新使用连接,如果它已被另一个线程打开。线程之间共享的唯一数据是URL队列。我查看了其他模块,但它们似乎需要更多的数据共享而不仅仅是一个网址。