Python3 三種Queue的異同


一、Queue(隊列)

Queue是python中的標准庫,可以直接import 引用,隊列默認遵循先進先出原則。

import queue
q = queue.Queue(10)
# 向隊列中添加元素
q.put('yang')
q.put(4)
q.put(['yan', 'xing'])

# 從隊列中取出元素,默認的隊列是先進先出的
q.get()
# 'yang'
q.get()
# 4
q.get()
# ['yan', 'xing']

當一個隊列為空的時候如果再用get取則會堵塞,所以取隊列的時候一般是用到get_nowait()方法,這種方法在向一個空隊列取值的時候會拋一個Empty異常,所以更常用的方法是先判斷一個隊列是否為空,如果不為空則取值。

隊列中常用的方法
Queue.qsize() 返回隊列的大小  
Queue.empty() 如果隊列為空,返回True,反之False  
Queue.full() 如果隊列滿了,返回True,反之False 
Queue.get([block[, timeout]]) 獲取隊列,timeout等待時間  
Queue.get_nowait() 相當Queue.get(False) 

非阻塞 Queue.put(item) 寫入隊列,timeout等待時間
Queue.put_nowait(item) 相當Queue.put(item, False)

二、multiprocessing中的Queue

multiprocessing中的Queue是多進程間進行通信的消息隊列。

from multiprocessing import Process,Queue
import os,time,random

#寫數據進程執行的代碼:
def write(p):
    for value in ['A','B','C']:
        print ('Write---Before Put value---Put %s to queue...' % value)
        p.put(value)
        print ('Write---After Put value')
        time.sleep(random.random())
        print ('Write---After sleep')

#讀數據進程執行的代碼:
def read(p):
    while True:
        print ('Read---Before get value')
        value = p.get(True)
        print ('Read---After get value---Get %s from queue.' % value)

if __name__ == '__main__':
    #父進程創建Queue,並傳給各個子進程:
    p = Queue()
    pw = Process(target=write,args=(p,))
    pr = Process(target=read,args=(p,))
    #啟動子進程pw,寫入:
    pw.start()
    #啟動子進程pr,讀取:
    pr.start()
    #等待pw結束:
    pw.join()
    #pr進程里是死循環,無法等待其結束,只能強行終止:
    pr.terminate()

三、multiprocessing.Manager.Queue

如果把上面的代碼改成下面的樣子:

if __name__=='__main__':    
    # 父進程創建Queue,並傳給各個子進程:
    q = Queue()
    p = Pool()
    pw = p.apply_async(write,args=(q,))    
    pr = p.apply_async(read,args=(q,))
    p.close()
    p.join()

本意是將會得到一個隊列,將其作為參數傳入進程池子里的每個子進程,但是卻得到報錯:RuntimeError: Queue objects should only be shared between processes through inheritance。

大意是:隊列對象不能在父子進程間通信。如果想要在進程池中使用隊列,則要使用multiprocessing的Mananger類:

if __name__=='__main__':
    manager = multiprocessing.Manager()
    # 父進程創建Queue,並傳給各個子進程:
    q = manager.Queue()
    p = Pool()
    pw = p.apply_async(write,args=(q,))
    time.sleep(0.5)
    pr = p.apply_async(read,args=(q,))
    p.close()
    p.join()

這樣這個隊列對象就可以在父進程與子進程間通信,不用池則不需要Manager。

總結

queue.Queue 是進程內非阻塞隊列
multiprocess.Queue 是跨進程通信隊列
前者是各自進程私有, 后者是各子進程共有
Manager.Queue和 Queue,multiprocessing.Queue本質上沒有太大關系,但它們有相同的方法。


免責聲明!

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



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