队列
概念介绍
创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。
方法介绍
Queue([maxsize]):创建共享的进程队列。maxsize是队列中允许的最大项数。省略此参数,则无大小限制
Queue的实例q具有以下方法:
q.get( [ block [ ,timeout ] ] ):返回q中的一个项目。如果q为空,此方法将阻塞,直到队列中有项目可用为止。block用于控制阻塞行为,默认为True. 如果设置为False,将引发Queue.Empty异常中。timeout是可选超时时间,用在阻塞模式中。如果在制定的时间间隔内没有项目变为可用,将引发Queue.Empty异常。
q.get_nowait() :同q.get(False)方法。
q.put(item [, block [,timeout ] ] ) :将item放入队列。如果队列已满,此方法将阻塞至有空间可用为止。block控制阻塞行为,默认为True。如果设置为False,将引发Queue.Full异常。timeout指定在阻塞模式中等待可用空间的时间长短。超时后将引发Queue.Full异常。
q.qsize() :返回队列中目前项目的正确数量。此函数的结果并不可靠,因为在返回结果和在稍后程序中使用结果之间,队列中可能添加或删除了项目。在某些系统上,此方法可能引发NotImplementedError异常。
q.empty() :如果调用此方法时 q为空,返回True。同q.qsize()不可靠,原因也同样。
q.full() :如果q已满,返回为True. 同q.qsize()不可靠,原因也同样。
代码实例
1、单独实例用法
from multiprocessing import Queue
q=Queue(3)
# put ,get ,put_nowait,get_nowait,full,empty简单实例
q.put(3)
q.put(3)
q.put(3)
# q.put(3) # 如果队列已经满了,程序就会停在这里,等待数据被别人取走,再将数据放入队列。
try:
q.put_nowait(3) # 可以使用put_nowait,如果队列满了不会阻塞,但是会因为队列满了而报错。
except:
print('队列已经满了')
# 因此,我们再放入数据之前,可以先看一下队列的状态,如果已经满了,就不继续put了。
print(q.full()) # True 满了
print(q.get())
print(q.get())
print(q.get())
# print(q.get()) # 同put方法一样,如果队列已经空了,那么继续取就会出现阻塞。
try:
q.get_nowait(3) # 可以使用get_nowait,如果队列满了不会阻塞,但是会因为没取到值而报错。
except:
print('队列已经空了')
print(q.empty()) # True 空了
2 批量数据放入队列再批量数据
import os
import time
import multiprocessing
# 向queue中输入数据的函数
def inputQ(queue):
info = str(os.getpid()) + '(put):' + str(time.asctime())
queue.put(info)
# 向queue中输出数据的函数
def outputQ(queue):
info = queue.get()
print ('%s%s%s'%(str(os.getpid()), '(get):',info))
# Main
if __name__ == '__main__':
multiprocessing.freeze_support()
record1 = [] # 存储输入进程
record2 = [] # 存储输出进程
queue = multiprocessing.Queue(3)
# 输入进程
for i in range(10):
process = multiprocessing.Process(target=inputQ,args=(queue,))
process.start()
record1.append(process)
# 输出进程
for i in range(10):
process = multiprocessing.Process(target=outputQ,args=(queue,))
process.start()
record2.append(process)
for p in record1:
p.join()
for p in record2:
p.join()
3 生产者消费者模型
from multiprocessing import Process,Queue
import time,random,os
def consumer(q):
while True:
res=q.get()
if res is None:break #收到结束信号则结束
time.sleep(random.randint(1,3))
print('%s 购买了 %s' %(os.getpid(),res))
def worker(q):
for i in range(10):
time.sleep(random.randint(1,3))
res='汽车%s' %i
q.put(res)
print('生产了 %s' %(os.getpid(),res))
q.put(None) #发送结束信号
if __name__ == '__main__':
q=Queue()
# 生产进程:即工人
p1=Process(target=producer,args=(q,))
# 消费进程:即顾客
c1=Process(target=consumer,args=(q,))
#开始
p1.start()
c1.start()
# 也可在主进程加入结束信号,但是要在生产进程结束后,再加入信号
# 如果有多个消费进程,就发送几个结束信号
p1.join()
q.put(None) #发送结束信号
print('主进程')
4 可连接的共享队列
常用的两个方法:
q.task_done():使用者使用此方法发出信号,表示q.get()返回的项目已经被处理
q.join():生产者将使用此方法进行阻塞,直到队列中所有项目均被处理。阻塞将持续到为队列中的每个项目均调用q.task_done()方法为止。
下面说明如何建立永远运行的进程,使用和处理队列上的项目。生产者将项目放入队列并等待它们被处理。
from multiprocessing import Process,JoinableQueue
import time,random,os
def consumer(q):
while True:
res=q.get()
time.sleep(random.randint(1,3))
print('%s 购买了 %s' %(os.getpid(),res))
q.task_done() #向q.join()发送一次信号,证明一个数据已经被取走了
def producer(name,q):
for i in range(10):
time.sleep(random.randint(1,3))
res='%s%s' %(name,i)
q.put(res)
print('生产了 %s' %(os.getpid(),res))
q.join() #生产完毕,使用此方法进行阻塞,直到队列中所有项目均被处理。
if __name__ == '__main__':
q=JoinableQueue()
#生产者进程:即工人
p1=Process(target=producer,args=('宝马',q))
p2=Process(target=producer,args=('奔驰',q))
p3=Process(target=producer,args=('法拉利',q))
#消费进程:即顾客
c1=Process(target=consumer,args=(q,))
c2=Process(target=consumer,args=(q,))
c1.daemon=True
c2.daemon=True
#开始
p_l=[p1,p2,p3,c1,c2]
for p in p_l:
p.start()
p1.join()
p2.join()
p3.join()
print('主进程')
# 主进程等--->p1,p2,p3等--->c1,c2
# p1,p2,p3结束了,证明c1,c2肯定全都收完了p1,p2,p3发到队列的数据
# 因而c1,c2也没有存在的价值了,不需要继续阻塞在进程中影响主进程了,所以设置成守护进程就可以了。