3.3.3 进程数据共享

进程间数据交互

我们知道,两个独立进程所使用的内存空间也是独立的,不可交互的。

但现实中就有那么些情况需要两个进程可以互相通信,怎么办?

我们需要一个中继、翻译、中间人,不管你叫他什么,只要知道他是用来转发数据的就行了。

Python中的这个中间人就叫queue,不是线程queue,是进程queue。使用方法和线程queue差不多。

示例如下:

from multiprocessing import Process, Queue

def f(q):
    q.put([42, None, 'Hello'])    #3 子进程给中间人传递消息


if __name__ == '__main__':
    q = Queue()    #1 中间人
    p = Process(target=f, args=(q, ))    #2 传递中间人给子进程
    p.start()
    print(q.get())    #4 父进程得到消息

结果

[42, None, 'Hello']

Pipe()

The Pipe() function returns a pair of connection objects connected by a pipe which by default is duplex (two-way). For example:

from multiprocessing import Process, Pipe


def f(conn):
    conn.send([42, None, 'hello'])    #3子进程执行的f()函数发送一条消息
    conn.close()


if __name__ == '__main__':
    parent_conn, child_conn = Pipe()    #1管道的两端
    p = Process(target=f, args=(child_conn,))
    p.start()    #2启动一个子进程,子进程执行f()函数
    print(parent_conn.recv())    #4输出父进程通过管道接收到的消息

结果

[42, None, 'hello']

The two connection objects returned by Pipe() represent the two ends of the pipe. Each connection object has send

由Pipe()函数返回的两个连接对象表示管道的两端。每个链接对象都由send()

() and recv() methods (among others). Note that data in a pipe may become corrupted if two processes (or threads) try

扫描二维码关注公众号,回复: 8378326 查看本文章

和recv()方法。注意如果两个进程(或线程)尝试同时从管道的同一头读取或者写入时管道中的数据可能出错。

to read from or write to the same end of the pipe at the same time. Of course there is no risk of corruption from processes

当然,多进程同时使用管道不同的终端,是没有出错风险的。

using different ends of the pipe at the same time.

以上2个方法,多进程的queue和pipe都只能实现进程间数据的传递,但还没有涉及进程间的数据共享

Managers

A manager object returned by Manager() controls a server process which holds Python objects and allows other processes

Manager()返回一个管理器对象,管理器对象控制一个服务进程,该进程持有Python对象并允许其他进程使用代理操作这些Python对象

to manipulate them using proxies.

A manager returned by Manager() will support

由Manager()返回的管理器支持以下类型

types list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value 

and Array. For example

示例

from multiprocessing import Manager, Process
import os

def f(d, l):
    d[1] = '1'
    d['2'] = 2
    d[0.25] = None
    l.append(os.getpid())    #4每次进程循环,添加当前进程ID
    print(l)

if __name__ == '__main__':
    m = Manager()    #1管理器对象
    d = m.dict()    #2管理器对象所持有的Python对象,字典
    l = m.list(range(5))    #同上,列表,这里预存了5个值
    p_list = []
    for i in range(10):
        p = Process(target=f, args=(d, l))    #3子进程执行f()函数,传递上面2个Python对象
        p.start()
        p_list.append(p)
    for res in p_list:
        res.join()
    print('dict: ', d)    #5输出结果
    print('list: ', l)

结果

[0, 1, 2, 3, 4, 7836]
[0, 1, 2, 3, 4, 7836, 9132]
[0, 1, 2, 3, 4, 7836, 9132, 10504]
[0, 1, 2, 3, 4, 7836, 9132, 10504, 11156]
[0, 1, 2, 3, 4, 7836, 9132, 10504, 11156, 10712]
[0, 1, 2, 3, 4, 7836, 9132, 10504, 11156, 10712, 7188]
[0, 1, 2, 3, 4, 7836, 9132, 10504, 11156, 10712, 7188, 15244]
[0, 1, 2, 3, 4, 7836, 9132, 10504, 11156, 10712, 7188, 15244, 6944]
[0, 1, 2, 3, 4, 7836, 9132, 10504, 11156, 10712, 7188, 15244, 6944, 13088]
[0, 1, 2, 3, 4, 7836, 9132, 10504, 11156, 10712, 7188, 15244, 6944, 13088, 12932]
dict:  {1: '1', '2': 2, 0.25: None}
list:  [0, 1, 2, 3, 4, 7836, 9132, 10504, 11156, 10712, 7188, 15244, 6944, 13088, 12932]

可以看到,父进程子进程对同一份数据进行了修改,实现了数据的共享。

猜你喜欢

转载自www.cnblogs.com/infinitecodes/p/12127376.html