TOP

4.3 队列/管道

IPA 通信

概念原理

创建/方法

Queue([maxsize]) 
  创建共享的进程队列。
  maxsize是队列中允许的最大项数。如果省略此参数,则无大小限制。


Queue的实例q具有以下方法:
q.get( [ block [ ,timeout ] ] )   返回q中的一个项目。
  q为空,此方法将阻塞,直到队列中有项目可用为止。
  block 用于控制阻塞行为,
    默认为True.
    设置为False,将引发Queue.Empty异常(定义在Queue模块中)。
  timeout 可选超时时间
    用在阻塞模式中
    如果在制定的时间间隔内没有项目变为可用,将引发Queue.Empty异常。
q.get_nowait( )   同q.get(False)方法。
q.put(item [, block [,timeout ] ] )   将item放入队列 , 如果队列已满,此方法将阻塞至有空间可用为止。
  block控制阻塞行为,
    默认为True。
    设置为False,将引发Queue.Empty异常(定义在Queue库模块中)。
  timeout指定在阻塞模式中等待可用空间的时间长短
    超时后将引发Queue.Full异常。
q.qsize()   返回队列中目前项目的正确数量。
  此函数的结果并不可靠,因为在返回结果和在稍后程序中使用结果之间,队列中可能添加或删除了项目
  在某些系统上,此方法可能引发NotImplementedError异常。 q.empty()   如果调用此方法时 q为空,返回True。
  如果其他进程或线程正在往队列中添加项目,结果是不可靠的。也就是说,在返回和使用结果之间,队列中可能已经加入新的项目。
q.full()   如果q已满,返回为True. 由于线程的存在,结果也可能是不可靠的(参考q.empty()方法)。。

  进程间通讯示例

import time
from multiprocessing import Process, Queue

def f(q):
    q.put([time.asctime(), 'hi', 'hello'])  #调用主函数中p进程传递过来的进程参数 put函数为向队列中添加一条数据。

if __name__ == '__main__':
    q = Queue() #创建一个Queue对象
    p = Process(target=f, args=(q,)) #创建一个进程
    p.start()
    print(q.get())  # ['Wed Jan 30 23:54:47 2019', 'hi', 'hello']
    # 子进程拿到了父进程的数据
    p.join()
View Code

生产者消费者模型

无信号纯阻塞的模型

from multiprocessing import Process,Queue
import time,random,os
def consumer(q):
    while True:
        res=q.get()
        time.sleep(random.randint(1,3))
        print('\033[45m%s 吃 %s\033[0m' %(os.getpid(),res))

def producer(q):
    for i in range(10):
        time.sleep(random.randint(1,3))
        res='包子%s' %i
        q.put(res)
        print('\033[44m%s 生产了 %s\033[0m' %(os.getpid(),res))

if __name__ == '__main__':
    q=Queue()
    #生产者们:即厨师们
    p1=Process(target=producer,args=(q,))

    #消费者们:即吃货们
    c1=Process(target=consumer,args=(q,))

    #开始
    p1.start()
    c1.start()
    print('')
View Code

 带信号的模型

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('\033[45m%s 吃 %s\033[0m' %(os.getpid(),res))

def producer(q):
    for i in range(10):
        time.sleep(random.randint(1,3))
        res='包子%s' %i
        q.put(res)
        print('\033[44m%s 生产了 %s\033[0m' %(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()
    print('')

 改良版——生产者消费者模型
View Code

多消费者时的带信号模型

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('\033[45m%s 吃 %s\033[0m' %(os.getpid(),res))

def producer(name,q):
    for i in range(2):
        time.sleep(random.randint(1,3))
        res='%s%s' %(name,i)
        q.put(res)
        print('\033[44m%s 生产了 %s\033[0m' %(os.getpid(),res))

if __name__ == '__main__':
    q=Queue()
    #生产者们:即厨师们
    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,))

    #开始
    p1.start()
    p2.start()
    p3.start()
    c1.start()

    p1.join() #必须保证生产者全部生产完毕,才应该发送结束信号
    p2.join()
    p3.join()
    q.put(None) #有几个消费者就应该发送几次结束信号None
    q.put(None) #发送结束信号
    print('')

 多个消费者的例子:有几个消费者就需要发送几次结束信号
View Code

 

posted @ 2019-01-30 23:58  羊驼之歌  阅读(220)  评论(0编辑  收藏  举报