进程间数据交互及共享

一、概述

 

 

之前我们讲述了进程之间的是通过进程中的Queue,来进行数据共享的,其实还有一种方式实现数据共享,那就是管道,pipe,以及数据共享manger

 二、数据通信

 

 

2.1、Pipe()函数

英文解释:The Pipe() function returns a pair of connection objects connected by a pipe which by default is duplex (two-way)。

中文解释:管道函数会返回由管道双方连接的一组连接对象,该管道默认是双向的(双向的)。

from multiprocessing import Process, Pipe
  
def f(conn):
    conn.send([42, None, 'hello'])  #发送消息给父进程
    conn.close()
  
if __name__ == '__main__':
    parent_conn, child_conn = Pipe()#管道生成返回两个实例,是双向的,这边把第1个作为父连接,第2个作为子连接。也可以,两者角色调换一下
    p = Process(target=f, args=(child_conn,))
    p.start()
    print(parent_conn.recv())   # 接收子进程的消息
    p.join()

 2.2、接收多次和发送多次

说明:上面我们只看到发送一次,接收一次,我们现在来看看,父进程和子进程都可以发送和接收。

from multiprocessing import Process, Pipe
 
def f(conn):
    conn.send([42, None, 'hello'])#发送两次
    conn.send("苏苏你好")
    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())
    print(parent_conn.recv())  #接收两次
    parent_conn.send("父亲发给你的")   #发送给子进程
    p.join()

 注意了:子进程如果向父进程发送两次,但是父进程接收三次,那么会一直卡在那边。

 三、共享

 

 

3.1、manger

说明:manger可以完成数据间的共享。

英文解释:

A manager object returned by Manager() controls a server process which holds Python objects and allows other processes to manipulate them using proxies.

A manager returned by Manager() will support types listdictNamespaceLockRLockSemaphoreBoundedSemaphoreConditionEventBarrierQueueValue and Array.

 

from multiprocessing import Process, Manager
import os
 
def f(d, l):
    d[os.getpid()] = os.getpid()
    l.append(os.getpid())
    print(l)
 
if __name__ == '__main__':
    with Manager() as manager:
        d = manager.dict()   #声明一个字典,注意,这个字典是用manger声明的,不是用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)

注意了:manger.dict()是用专门的语法生产一个可在多进程之间进行传递和共享的一个字典,就是dict(),这个时候生产的对象就是d。

疑问:这边要不要加锁呐?

答案:不用加锁,因为这个manger已经帮你加锁了,它就默认不允许两个进程同时修改一份数据。两个进程没有办法同时修改一份数据,进程之间是独立的,它自己也要加锁,因为它把自己的东西同时copy好几份,跟刚刚的那个Queue一样,copy10个字典最终合成一个字典。

posted @ 2017-10-17 10:51  人生是一场修行  阅读(200)  评论(0)    收藏  举报