一、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本质上没有太大关系,但它们有相同的方法。