zoukankan      html  css  js  c++  java
  • python 学习笔记

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

    跟多资料可以阅读:http://www.tuicool.com/articl...

    # 示例代码
    # 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的一些说明已经写在代码中了。

  • 相关阅读:
    新版ubuntu中打开终端的方法和安装ssh 的方法
    HTML中利用404将老域名重定向到新域名
    KeelKit 1.0.3500.25185
    如何制作VSPackage的安装程序
    一副漫画:IE6滚回你老家去
    “表单控件”与“实体类”
    VS2005中得到 Web页面 或 窗体的 IDesignerHost
    一句SQL搞定分页
    CodeDom Assistant CodeDom的强大工具, 有些BUG修正了下,发到CodePlex,大家有需要的可以看看
    VS2005 出现 The OutputPath property is not set for this project. 错误的解决方法
  • 原文地址:https://www.cnblogs.com/qunxiadexiaoxiangjiao/p/8428764.html
Copyright © 2011-2022 走看看