zoukankan      html  css  js  c++  java
  • python 多进程数据交互及共享

    多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。

    不同进程之间内存是不共享的,要实现两个进程间的数据交换,可以用以下方法:

    queues

    使用方法和threading里面的queue差不多

    from multiprocessing import Process,Queue
    
    def f(q):
        q.put([2,None,'hello'])
    
    if __name__ =='__main__':
        q = Queue()
        p = Process(target=f,args=(q,))
        p.start()
        print(q.get())
        p.join()
    

     运行结果

    [2, None, 'hello']
    

    多进程中,对于一个变量,每个进程都是复制了一份,所以每个进程之间修改数据互不影响。 Queue()方法相当于第三方,把进程A的数据序列化后传给进程B 反序列化得到数据。并不是一个共享的变量。而是实现了数据的传递。

    Pipes 管道

    类似于socket 一端发送,一端接收,实现通信。

    from multiprocessing import Process,Pipe
    
    def f(conn):
        conn.send([5,'hello'])
        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()
    

     运行结果

    [5, 'hello']
    

     发送方和接收方的关系,也和socket类似,发送方发送几次,接收方就要接收几次。接收方如果接收的次数多于发送方,那么接收方就会卡住,直到发送方在发送一次。

    相互通信

    def f(conn):
        conn.send([5,'hello'])   #发送数据
        print(conn.recv())         #接收数据
        conn.close()
    
    
    if __name__ =='__main__':
        parent_conn,child_conn = Pipe()
        p = Process(target=f,args=(child_conn,))
        p.start()
        print(parent_conn.recv())         #接收数据
        parent_conn.send("hehe你好")  #发送数据
        p.join()
    

     Managers

    由manager()返回的manager对象控制一个包含Python对象的服务器进程,并允许其他进程使用代理来操作它们。

    由manager()返回的管理器将支持类型列表、命令、名称空间、锁、RLock、信号量、BoundedSemaphore、Condition、Event、Barrier、Queue、Value和Array。

    from multiprocessing import Process, Manager
    
    
    def f(d, l):
        d[1] = '1'
        d['2'] = 2
        d[0.25] = None
        l.append(1)
        print(l)
    
    
    if __name__ == '__main__':
        with Manager() as manager:
            d = manager.dict()  #生成一个字典,可以在多个进程中传递和共享。
    
            l = manager.list(range(5)) #生成一个列表,在多个进程中传递和共享。
            p_list = []    #存放进程对象
            for i in range(10):
                p = Process(target=f, args=(d, l))
                p.start()
                p_list.append(p)
            for res in p_list:
                res.join()  #等待进程结束
    
            print(d)
            print(l)
    

     运行结果

    [0, 1, 2, 3, 4, 1]
    [0, 1, 2, 3, 4, 1, 1]
    [0, 1, 2, 3, 4, 1, 1, 1]
    [0, 1, 2, 3, 4, 1, 1, 1, 1]
    [0, 1, 2, 3, 4, 1, 1, 1, 1, 1]
    [0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1]
    [0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1]
    [0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1]
    [0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    [0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    {0.25: None, 1: '1', '2': 2}
    [0, 1, 2, 3, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    

     以上实现了进程之间的数据共享,不是数据传递,而是真正的共享。并且可以同时修改。

    Manager()内部有加锁机制,不允许两个进程同时修改一份数据,因为进程的数据是独立的。

  • 相关阅读:
    新手学习FFmpeg
    新手学习FFmpeg
    新手学习FFmpeg
    进阶计划
    面试题汇总
    grep命令
    Quartz教程三:Job与JobDetail介绍
    spring boot热部署
    Quartz学习——SSMM(Spring+SpringMVC+Mybatis+Mysql)和Quartz集成详解(四)
    SpringBoot集成篇(二) 异步调用Async
  • 原文地址:https://www.cnblogs.com/qing-chen/p/7688343.html
Copyright © 2011-2022 走看看