2012-04-01 90 views
2

这是一个两部分问题。首先是你如何正确关闭与urllib2的连接?我见过很多例子,并且我采用了我能找到的最佳解决方案。但是,关闭文件似乎存在问题。如何关闭连接并重新使用urllib2连接?

目前我使用contextlib收盘()如下:

try: 
     with closing(self.opener.open(self.address, 
             None, 
             self.timeout)) as page: 
      self.data = page.read() 
    except: 
     # bail out.. 

然而,很长一段时间在OSX后,我仍然得到“太多打开文件”的错误。我使用ulimit将文件增加到2000以上。我还将内核的最大文件设置为> 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。

回答

4

我会推荐滴urllib2,并尝试出色的Requests库。

它会自动处理重新使用和关闭连接。 (docs

您可能也对支持异步请求感兴趣。 (docs

+0

我将给出这个快速的一击,看看我是否可以用请求替换urllib2的开启者功能。我担心的是与其他代码的影响。我当然愿意尝试一下!谢谢 – 2012-04-01 04:26:24

+0

我做了一些初步测试,看起来效果很好。我会花时间看看爬虫是否死亡。我仍然对这个问题有更多的想法感兴趣,所以我将在标记解决之前等待。 – 2012-04-01 04:37:54