Python利用Queue、Pipe实现进程间通信

多个进程之间肯定是要能够互相通信的,Python为进程通信提供了许多机制,我们以multiprocessing模块下的QueuePipe为例。

Queue

Queue是多进程安全队列,使用Queue可以实现多进程之间的数据传递。

1.Queue的常用方法

Queue.get(block=True,timeout) 

1)获取队列的一条消息,然后将该消息自队列中移除。参数block默认为True

2)如果block为True,且未设置timeout,当在Queue为空时调用该方法,该方法将被阻塞,直到从Queue中读取到数据为止;如果设置了timeout,则会等待timeout秒,之后若仍为读到任何数据,则抛出"Queue Empty"异常。

3)如果block为False,调用该方法时Queue为空,则立即抛出"Queue Empty"异常。

Queue.get_nowait()

相当于Queue.get(False)。

Queue.put(item,block=True,timeout)

1)将消息item写入Queue,block默认为True

2)如果block为True,且未设置timeout,当在调用该方法时发现Queue已无空间可写入,此时该方法将被堵塞,直到Queue能够写入为止;如果设置了timeout,则会等待timeout秒,若之后仍然无法写入,抛出"Queue.Full"异常。

3)如果block为False,且调用该方法时Queue已无空间可写入,立刻抛出"Queue.Full"异常。

Queue.put_nowait(item)

相当于Queue.put(item,False)。

Queue.qsize()

返回Queue中目前的消息数量。这个结果并不一定准确,因为在返回结果直程序使用结果之间的时间内,Queue中的item数量可能已经变化,这可能会引发异常。

Queue.empty()

1)判断Queue是否为空,是空返回True,否则返回False。

2)同Queue.qsize(),该方法的结果也是不可靠的。

Queue.full()

1)判断Queue是否已满,是返回True,反之返回False。

2)同Queue.empty()。

Queue.close()

关闭Queue,调用该方法后无法再向Queue中添加数据,但曾经被堵塞的写入操作或者在调用close()之前但还未完成的操作仍将继续完成,Queue将在所有这些操作完成后立即关闭。

另外注意:初始化Queue时,可以设置Queue的最大可接受信息数量,如果未设置或者设置为负值,则表示可接受的信息数量无限制,直到全部内存被使用。

2.Queue实现进程间通信

我们知道进程的内存空间都是互相独立的,那么它们是如何用Queue实现通信的呢?看一个示例。

示例:

from multiprocessing import Process,Queue
def read(q):
    print('Process is reading...')
    while True:
        if not q.empty():
            value = q.get()
            print('%s is successfully read in from Queue.' % (value))
        else:
            break
def write(q):
    print('Process is writing...')
    for value in "HELLO":
        print('Put %s to Queue successfully.' % (value))
        q.put(value)
if __name__ == '__main__':
    q = Queue()
    pr = Process(target=read,args=(q,))
    pw = Process(target=write,args=(q,))
    pw.start()
    pw.join()
    pr.start()
    pr.join()
    print('A successful communication.')

运行结果:

Process is writing...
Put H to Queue successfully.
Put E to Queue successfully.
Put L to Queue successfully.
Put L to Queue successfully.
Put O to Queue successfully.
Process is reading...
H is successfully read in from Queue.
E is successfully read in from Queue.
L is successfully read in from Queue.
L is successfully read in from Queue.
O is successfully read in from Queue.
A successful communication.

<分析>

示例中创建了两个子进程,pw和pr,可以看到我们用Queue实现了两个子进程间的通信。pw将数据写入Queue中,而pr将数据从Queue中读出,需要注意的就是在调用pw.start()时接着就要调用pw.join(),这样才能保证数据全部写入。如果要想实现父进程与子进程间的通信,只需要在主程序中调用get()、put()方法即可。

注意点:Queue同样遵循队列数据先入先出的规则;

Pipe

如果使用Pipe来实现进程通信,程序会调用multiprocessing.Pipe()函数创建一个管道,该函数会返回一个元组,元组中包括两个PipeConnection对象,代表管道的两个连接端,即管道连接的两个进程。

应当注意的是,Pipe()有默认参数duplex,它默认管道为全双工的,如果将duplex映射为False,那么PipeConnection对象1只能用于接收,PipeConnection对象2只能用于发送

1.PipeConnection对象(设为pcn)的常用方法

pcn.send(obj)

1)发送一个obj对象给管道的另一端。该对象必须是与序列化兼容的,即可picklable的。

2)该方法发送的数据只能由recv()方法接收

pcn.recv()

接受Pipe另一端通过send()方法发送过来的数据。

pcn.fileno()

返回关于连接所使用的整数文件描述符。

pcn.close()

关闭连接。如果pcn对象被垃圾回收,则自动调用此方法。

pcn.poll(timeout)

1)判断连接中是否还有数据可以读取,是返回True,否则返回False。

2)timeout指定等待的最长期限,如果忽略timeout,该方法将立即返回结果,如果timeout为None,该方法将无限期的等待数据到达。

pcn.send_bytes(buffer,offset,size)

1)发送字节缓冲区中的数据。

2)buffer是支持缓冲区接口的任意对象,如果未指定offset和size,则默认发送全部数据,如果指定,则发送buffer字节串中从offset位置开始,长度为size的字节数据。

3)该方法发送的数据只能由recv_bytes()方法接收

pcn.recv_bytes(maxlength)

接受send_bytes()发送的数据并返回,maxlength用于指定最多接收的字节数。

pcn.recv_bytes_info(buffer,offset)

功能上与recv_bytes()方法类似,只不过该方法将接收到的数据放在buffer中。

2.Pipe实现进程间通信

示例:

from multiprocessing import Process,Pipe
def send(p,info):
    print('Process send...')
    for value in info:
        print('Send %s ' % (value))
        p.send(value)
def recv(p):
    print('Process reveive...')
    while True:
        if p.poll():
            print('recv %s ' % (p.recv()))
        else:
            break
if __name__ == '__main__':
    p = Pipe()
    ps = Process(target=send,args=(p[0],'HELLO'))
    pr = Process(target=recv,args=(p[1],))
    ps.start()
    ps.join()
    print()
    pr.start()
    pr.join()
    print()
    print('A successful communication.')       

运行结果:

Process send...
Send H
Send E
Send L
Send L
Send O

Process reveive...
recv H
recv E
recv L
recv L
recv O

A successful communication.

<分析>

用Pipe实现进程间通信与使用Queue差不多,本例中创建了两个子进程并实现了它们的通信,这里注意的是用Pipe创建一个管道时返回的是一个元组,所以本例中的p[0]、p[1]是元组中的前两个成员,当然你也可以定义两个变量来分别接受Pipe()的返回值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值