一、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本質上沒有太大關系,但它們有相同的方法。