zoukankan      html  css  js  c++  java
  • 管道(了解)---不推荐使用

    #创建管道的类:
    Pipe([duplex]):在进程之间创建一条管道,并返回元组(conn1,conn2),其中conn1,conn2表示管道两端的连接对象,强调一点:必须在产生Process对象之前产生管道
    #参数介绍:
    dumplex:默认管道是全双工的,如果将duplex射成False,conn1只能用于接收,conn2只能用于发送。
    #主要方法:
        conn1.recv():接收conn2.send(obj)发送的对象。如果没有消息可接收,recv方法会一直阻塞。如果连接的另外一端已经关闭,那么recv方法会抛出EOFError。
        conn1.send(obj):通过连接发送对象。obj是与序列化兼容的任意对象
     #其他方法:
    conn1.close():关闭连接。如果conn1被垃圾回收,将自动调用此方法
    conn1.fileno():返回连接使用的整数文件描述符
    conn1.poll([timeout]):如果连接上的数据可用,返回True。timeout指定等待的最长时限。如果省略此参数,方法将立即返回结果。如果将timeout射成None,操作将无限期地等待数据到达。
     
    conn1.recv_bytes([maxlength]):接收c.send_bytes()方法发送的一条完整的字节消息。maxlength指定要接收的最大字节数。如果进入的消息,超过了这个最大值,将引发IOError异常,并且在连接上无法进行进一步读取。如果连接的另外一端已经关闭,再也不存在任何数据,将引发EOFError异常。
    conn.send_bytes(buffer [, offset [, size]]):通过连接发送字节数据缓冲区,buffer是支持缓冲区接口的任意对象,offset是缓冲区中的字节偏移量,而size是要发送字节数。结果数据以单条消息的形式发出,然后调用c.recv_bytes()函数进行接收    
     
    conn1.recv_bytes_into(buffer [, offset]):接收一条完整的字节消息,并把它保存在buffer对象中,该对象支持可写入的缓冲区接口(即bytearray对象或类似的对象)。offset指定缓冲区中放置消息处的字节位移。返回值是收到的字节数。如果消息长度大于可用的缓冲区空间,将引发BufferTooShort异常。
    介绍

    队列的实现就是管道+锁

    简单使用

    from multiprocessing import Process, Pipe
    
    
    def f(conn):
        conn.send("Hello The_Third_Wave")
        conn.close()
    
    
    if __name__ == '__main__':
        parent_conn, child_conn = Pipe()
        p = Process(target=f, args=(child_conn,))
        p.start()
        print(parent_conn.recv())
        p.join()
    View Code

    应该特别注意管道端点的正确管理问题。如果是生产者或消费者中都没有使用管道的某个端点,就应将它关闭。这也说明了为何在生产者中关闭了管道的输出端,在消费者中关闭管道的输入端。如果忘记执行这些步骤,程序可能在消费者中的recv()操作上挂起。管道是由操作系统进行引用计数的,必须在所有进程中关闭管道后才能生成EOFError异常。因此,在生产者中关闭管道不会有任何效果,除非消费者也关闭了相同的管道端点。 

    from multiprocessing import Pipe
    left,right = Pipe()
    left.send('1234')
    print(right.recv())

    执行输出:1234

    管道实例化之后,形成2端。默认情况下,管道是双向的
    左边send,右边recv
    一端send和recv,会阻塞
    它不是走TCP和UDP
    它是一台机器的多个进程

    引发EOFError错误的例子

    from multiprocessing import Process, Pipe
    
    
    def f(parent_conn, child_conn):
        parent_conn.close()  # 这句加上是主动触发异常,不写close将不会引发EOFError
        while True:
            try:
                print(child_conn.recv())
            except EOFError:
                print('----')
                child_conn.close()
                break
    
    
    if __name__ == '__main__':
        # 在进程之间创建一条管道,并返回元组(conn1,conn2),其中conn1和conn2是表示管道两端的Connection对象
        parent_conn, child_conn = Pipe()
        p = Process(target=f, args=(parent_conn, child_conn,))
        p.start()
        child_conn.close()  # 关闭连接
        parent_conn.send('hello1')
        parent_conn.send('hello2')
        parent_conn.send('hello3')
        parent_conn.close()
        p.join()  # 等待子进程结束
        
    '''
    hello1
    hello2
    hello3
    ----
    '''
    View Code

    使用pipe来实现生产消费者模型

    from multiprocessing import Process,Pipe
    
    def consumer(p,name):
        produce, consume=p
        produce.close()
        while True:
            try:
                baozi=consume.recv()
                print('%s 收到包子:%s' %(name,baozi))
            except EOFError:
                break
    
    def producer(seq,p):
        produce, consume=p
        consume.close()
        for i in seq:
            produce.send(i)
    
    if __name__ == '__main__':
        produce,consume=Pipe()
    
        c1=Process(target=consumer,args=((produce,consume),'c1'))
        c1.start()
    
    
        seq=(i for i in range(10))
        producer(seq,(produce,consume))
    
        produce.close()
        consume.close()
    
        c1.join()
        print('主进程')
    View Code

    多个消费者之间的竞争带来数据不安全问题,

    from multiprocessing import Process,Pipe,Lock
    
    def consumer(p,name,lock):
        produce, consume=p
        produce.close()
        while True:
            lock.acquire()
            baozi=consume.recv()
            lock.release()
            if baozi:
                print('%s 收到包子:%s' %(name,baozi))
            else:
                consume.close()
                break
    
    
    def producer(p,n):
        produce, consume=p
        consume.close()
        for i in range(n):
            produce.send(i)
        produce.send(None)
        produce.send(None)
        produce.close()
    
    if __name__ == '__main__':
        produce,consume=Pipe()
        lock = Lock()
        c1=Process(target=consumer,args=((produce,consume),'c1',lock))
        c2=Process(target=consumer,args=((produce,consume),'c2',lock))
        p1=Process(target=producer,args=((produce,consume),10))
        c1.start()
        c2.start()
        p1.start()
    
        produce.close()
        consume.close()
    
        c1.join()
        c2.join()
        p1.join()
        print('主进程')
    View Code
  • 相关阅读:
    ASP.NET MVC5 实现网址伪静态
    用c#中的WebBrowser抢小米F码,抢小米手机以及自动测试实现原理
    MVC授权
    使用grid++report打印选中行
    对Spring.Net+NHibenate+Asp.Net Mvc+Easyui框架的个人认识
    hibernate+spring+mvc+Easyui框架模式下使用grid++report的总结
    一个关于Linq对引用类型元素集合去重问题的思考
    Spring MVC PageNotFound.noHandlerFound No mapping found for HTTP request with URI
    ueditor 1.4.3.2 独立/单独 上传图片框原理
    (兼容IE6)又一个提示框思密达,腾讯UED 201401242352
  • 原文地址:https://www.cnblogs.com/mmyy-blog/p/9429286.html
Copyright © 2011-2022 走看看