python多進程multiprocessing模塊中Queue的妙用


  最近的部門RPA項目中,小爬為了提升爬蟲性能,使用了Python中的多進程(multiprocessing)技術,里面需要用到進程鎖Lock,用到進程池Pool,同時利用map方法一次構造多個process。Multiprocessing的使用確實能顯著提升爬蟲速度,不過程序交由用戶使用時,缺乏一個好的GUI窗口來顯示爬蟲進度。之前的文章中使用了Chrome瀏覽器來渲染js腳本生成了進度條。但是鑒於Chrome在運行時十分吃內存資源,用Chrome只是生成一個進度條難免有些“大材小用”,所以,小爬決定使用Tkinter庫來制作進度條,進而擺脫對chrome瀏覽器的依賴。

  要制作進度條,就得有計數器存儲爬蟲的總數,當前的爬取數甚至是當前的耗費時間等作為存儲變量。考慮到各個進程之間無法直接通信,這個當前量和總量如何得到,就只能借助multiprocessing中的Queue類了。根據官方文檔,multiprocessing中的Queue 類幾乎完美克隆了Queue.Queue中的功能,但是它是專為多進程間的通信單獨設計的。

 

透過一個簡單的例子看下Queue是如何運用的:

from multiprocessing import Process, Queue

def f(q):
    q.put([42, None, 'hello'])

if __name__ == '__main__':
    q = Queue()
    p = Process(target=f, args=(q,))
    p.start()
    print q.get()    # prints "[42, None, 'hello']"
    p.join()

從上面的例子可以看到,此處的Queue示例出的q對象非常靈活,使用Ipython的代碼提示功能可以輕松知道q對象含以下方法,供用戶調用:

比如:

1、它主要是通過q.put()來入列,該方法支持存入單個變量,也支持通過列表一次入列多個不同類型的元素,異常靈活多變。

2、q.qsize()可以得到當前隊列的元素總數。

3、q.empty()可以判斷當前隊列中是否還有值,返回一個布爾型的結果。如:

In [36]: q.empty()
Out[36]: True

4、通過q.get()方法來出隊列。

這樣我們就可以靈活使用隊列來在各進程間通信和制作進度條了。

我們在爬蟲中,往往會遇到一個這樣的情況,目錄頁和詳情頁的信息需要結合到一個item中存儲起來,它就可以巧妙借助Queue來實現。

上面的例子中,我一次存入了url,bpmDefName,dataId,afFormNumber 等多個字段信息。

后面我們再從queue中取出一個結果,則該結果是包含 url,bpmDefName,dataId,afFormNumber 多個信息的元組。進而得到元組的每個元素與詳情頁的相關字段拼接到一起,形成一行信息。代碼示例如下:

最后通過Q.qsize()方法判斷隊列中的元素是否已完全取出,來實時計算爬蟲進度和決定后續動作,非常方便!

有了multiprocessing模塊的Queue類和它提供的諸多方法,制作進度條和關聯多個item信息,便不再是難題!

更詳細的multiprocessing模塊的Queue類介紹,可以參見python官方的文檔說明:

https://docs.python.org/3/library/multiprocessing.html#multiprocessing.Queue

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM