博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python 学习笔记 - Queue & Pipes,进程间通讯
阅读量:6507 次
发布时间:2019-06-24

本文共 2790 字,大约阅读时间需要 9 分钟。

上面写了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。那么就建立好了一个输入在主进程,输出在子进程的管道。
原理示意图如下:
Pipe原理示意图
跟多资料可以阅读:

# 示例代码# coding=utf-8from multiprocessing import Pipe, Processdef 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,可以捕获并且退出子进程            breakif __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-8from multiprocessing import Queue, Processfrom Queue import Empty as QueueEmptyimport randomdef 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:            breakdef 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" % valueif __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的一些说明已经写在代码中了。

转载地址:http://vnzfo.baihongyu.com/

你可能感兴趣的文章
ArrayList底层实现
查看>>
【转载】Java程序设计入门 (二)
查看>>
which、whereis、location和fand的区别
查看>>
IP地址和子网划分学习笔记之《子网掩码详解》
查看>>
单词最近距离
查看>>
高性能网站性能优化与系统架构(ZT)
查看>>
iOS发展- 文件共享(使用iTunes导入文件, 并显示现有文件)
查看>>
标准输入的原理:cin与scanf
查看>>
c# 正则提取小例子
查看>>
程序猿知道英语词汇
查看>>
数据存储(两)--SAX发动机XML记忆(附Demo)
查看>>
ECSHOP添加购物车加图片飞入效果
查看>>
谈谈SQL 语句的优化技术
查看>>
Nova 操作汇总(限 libvirt 虚机) [Nova Operations Summary]
查看>>
数据结构Java实现04----循环链表、仿真链表
查看>>
ecshop如何判断缓存文件是否能更新
查看>>
打印xls注意事项
查看>>
JSP模板文本
查看>>
javascript于boolean类型转换,运营商&&和|| 返回值
查看>>
iOS远程推送之友盟Push
查看>>