2012-04-01 91 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