python 进程间通信效率_python 学习笔记 - Queue & Pipes,进程间通讯

上面写了Python如何创建多个进程,但是前面文章中创建的进程都是哑巴和聋子,自己顾自己执行,不会相互交流。

那么如何让进程间相互说说话呢?

Python为我们提供了一个函数multiprocessing.Pipe

和一个类:multiprocessing.Queue。

multiprocessing.Pipe()

multiprocessing.Pipe()即管道模式,调用Pipe()返回管道的两端的Connection。

Python官方文档的描述:

Returns a pair (conn1, conn2) of Connection objects representing the ends of a pipe.

因此, Pipe仅仅适用于只有两个进程一读一写的单双工情况,也就是说信息是只向一个方向流动。例如电视、广播,看电视的人只能看,电视台是能播送电视节目。

Pipe的读写效率要高于Queue。

进程间的Pipe基于fork机制建立。

当主进程创建Pipe的时候,Pipe的两个Connections连接的的都是主进程。

当主进程创建子进程后,Connections也被拷贝了一份。此时有了4个Connections。

此后,关闭主进程的一个Out Connection,关闭一个子进程的一个In Connection。那么就建立好了一个输入在主进程,输出在子进程的管道。

原理示意图如下:

# 示例代码

# coding=utf-8

from multiprocessing import Pipe, Process

def son_process(x, pipe):

_out_pipe, _in_pipe = pipe

# 关闭fork过来的输入端

_in_pipe.close()

while True:

try:

msg = _out_pipe.recv()

print msg

except EOFError:

# 当out_pipe接受不到输出的时候且输入被关闭的时候,会抛出EORFError,可以捕获并且退出子进程

break

if __name__ == '__main__':

out_pipe, in_pipe = Pipe(True)

son_p = Process(target=son_process, args=(100, (out_pipe, in_pipe)))

son_p.start()

# 等pipe被fork 后,关闭主进程的输出端

# 这样,创建的Pipe一端连接着主进程的输入,一端连接着子进程的输出口

out_pipe.close()

for x in range(1000):

in_pipe.send(x)

in_pipe.close()

son_p.join()

print "主进程也结束了"

总结一下:

上面的代码中主要用到了pipe的send()、recv()、close()方法。当pipe的输入端被关闭,且无法接收到输入的值,那么就会抛出EOFError。

新建一个Pipe(duplex)的时候,如果duplex为True,那么创建的管道是双向的;如果duplex为False,那么创建的管道是单向的。

multiprocessing.Queue

Queue据官方文档也是基于pipe的实现。

Queue的使用主要是一边put(),一边get().但是Queue可以是多个Process 进行put操作,也可以是多个Process进行get()操作。

Demo:

# coding=utf-8

from multiprocessing import Queue, Process

from Queue import Empty as QueueEmpty

import random

def getter(name, queue):

print 'Son process %s' % name

while True:

try:

value = queue.get(True, 10)

# block为True,就是如果队列中无数据了。

#   |—————— 若timeout默认是None,那么会一直等待下去。

#   |—————— 若timeout设置了时间,那么会等待timeout秒后才会抛出Queue.Empty异常

# block 为False,如果队列中无数据,就抛出Queue.Empty异常

print "Process getter get: %f" % value

except QueueEmpty:

break

def putter(name, queue):

print "Son process %s" % name

for i in range(0, 1000):

value = random.random()

queue.put(value)

# 放入数据 put(obj[, block[, timeout]])

# 若block为True,如队列是满的:

#  |—————— 若timeout是默认None,那么就会一直等下去

#  |—————— 若timeout设置了等待时间,那么会等待timeout秒后,如果还是满的,那么就抛出Queue.Full.

# 若block是False,如果队列满了,直接抛出Queue.Full

print "Process putter put: %f" % value

if __name__ == '__main__':

queue = Queue()

getter_process = Process(target=getter, args=("Getter", queue))

putter_process = Process(target=putter, args=("Putter", queue))

getter_process.start()

putter_process.start()

Queue的一些说明已经写在代码中了。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值