专栏名称: dwzb
目录
相关文章推荐
51好读  ›  专栏  ›  dwzb

Manager进程之间共享数据

dwzb  · 掘金  ·  · 2018-03-13 10:54

正文

Manager进程之间共享数据

本文首发于 知乎
本文分为如下部分

  • 引言
  • 初试manager
  • 注意事项
  • 分布式进程

引言

在多进程中,每一个进程都有自己的变量拷贝,所以主进程中的一个变量传入其他进程修改,得到的结果仍然存储于那个进程中,主进程中这个变量其实相当于没有被修改过。为了能让其他进程的修改能够同步到主进程上来,需要创建能在多个进程之间共享的变量。

举一个例子

from multiprocessing import Process
def f1(x, l):
x += 1
l.append(2)
def f2(x, l):
x -= 2
l.append(3)
if __name__ == '__main__':
x = 0
l = [1]
p1 = Process(target=f1, args=(x, l))
p2 = Process(target=f2, args=(x, l))
p1.start()
p2.start()
p1.join()
p2.join()
print(x, l)

运行结果为

0 [1]

x l 都没有被改变,因为它们是放在其他进程中修改的。

初试manager

我们在前面的文章中提到了进程之间共享数据的一些方法,如 Queue pipe value ,不过 multiprocessing 模块还提供了一种更加高级的封装,即用 Manager 来创建变量用于进程之间共享,我们直接来看下面一个例子

from multiprocessing import Process, Manager
def f1(ns, l):
ns.x += 1
l.append(2)
def f2(ns, l):
ns.x -= 2
l.append(3)
if __name__ == '__main__':
manager = Manager()
ns = manager.Namespace()
l = manager.list([1])
ns.x = 0
p1 = Process(target=f1, args=(ns, l))
p2 = Process(target=f2, args=(ns, l))
p1.start()
p2.start()
p1.join()
p2.join()
print(ns, l)

结果如下

Namespace(x=-1) [1, 2, 3]

上面代码涉及到了 manager.Namespace() manager.list() 两个方法,前者可以通过 . 来创建各种变量,后者专门用来创建list,用 manager 方法创建出来的变量可以在不同进程之中修改。

manager 创造的其他类型详见 官网

注意事项

有时候使用 manager 仍会发现变量没有被其他进程改变,比如使用 manager.Namespace() 创建列表修改无效,或 manager.list() 创建多层列表时里面列表中的元素修改无效。这是因为它们是可变对象,修改时内存地址不变,于是主进程还是读取原来的地址,独到的还是原来的值。

这个回答 中的代码非常恰当,我就直接贴在这里了

import multiprocessing
import time
def f(ns, ls, di):
ns.x += 1
ns.y[0] += 1
ns_z = ns.z
ns_z[0] += 1
ns.z = ns_z
ls[0] += 1
ls[1][0] += 1
ls_2 = ls[2]
ls_2[0] += 1
ls[2] = ls_2
di[0] += 1
di[1][0] += 1
di_2 = di[2]
di_2[0






请到「今天看啥」查看全文