多处理器.Manager()具有全局变量的怪异行为



我对multiprocessing.Manager类有一个问题,当管理器对象是全局变量时,它的行为非常奇怪。

代码1:

import multiprocessing
from multiprocessing import Manager
manager = Manager()
list1 = manager.list(range(4))
dict1 = manager.dict({"d":1,"f":2})
def process1(list1,dict1):
    print "process1"
    dict1["3"] = 123
    list1.append(10)
def run():
    print "start"
    global list1
    global dict1
    print "list1",list1
    print "dict1",dict1
if __name__ == '__main__':
    print "start"
    j = multiprocessing.Process(target=process1, args=(list1,dict1))
    j.start()
    j.join()
    run()

输出1:

start
process1
start
list1 [0, 1, 2, 3, 10]
dict1 {'3': 123, 'd': 1, 'f': 2}

好的,这意味着全局变量̀list1dict1已经被process1修改了。

问题是,当我尝试更换list1dict1时,它不起作用!

代码2:

import multiprocessing
from multiprocessing import Manager
manager = Manager()
list1 = manager.list(range(4))
dict1 = manager.dict({"d":1,"f":2})
def process1(list1,dict1):
    print "process1"
    dict1["3"] = 123
    list1 = manager.list(range(100,104))
def run():
    print "start"
    global list1
    global dict1
    print "list1",list1
    print "dict1",dict1
if __name__ == '__main__':
    print "start"
    j = multiprocessing.Process(target=process1, args=(list1,dict1))
    j.start()
    j.join()
    run()

输出2:

start
process1
start
list1 [0, 1, 2, 3]
dict1 {'3': 123, 'd': 1, 'f': 2}

知道为什么它返回初始列表[0, 1, 2, 3]而不是[100, 101, 102, 103]吗?

虽然Manager.list对象在进程之间共享,但绑定到该对象的名称根本不会共享,即使在所有进程中使用相同的名称也不会共享。global意味着在运行模块的过程中,在整个模块中都可以看到相同的绑定(除非在某些本地范围中被覆盖);这并不意味着仅仅因为multiprocessing被导入就意味着更多;-)

具体地,主进程中的名称list1与工作进程中的名字list1无关。它们之间唯一的关系是,这两个名称最初恰好绑定到Manager.list的一个共享实例。这通常是你想要从他们那里得到的。在任何一个进程中,将名称list1重新绑定到某个其他对象都不会对名称list1在任何其他进程中绑定到的对象产生影响。

因此,在第二个示例中,在工作进程中,名称list1变为(重新)绑定到一个新的manager.list(range(100,104))实例。这对主进程中名称list1的绑定没有任何影响。工作进程也没有任何可能的方法来更改任何其他进程中任何名称的绑定——如果发生这种情况,那将是一场噩梦。

不过,您可以更改共享对象的值。但你似乎已经知道了。例如,进行

list1[:] = range(100,104)

相反,不更改绑定,而是替换共享Manager.list实例的整个内容(因此主进程也会看到新的列表内容,不是因为名称相同,而是因为两个名称都绑定到同一对象)。

顺便说一句,请注意,在process1函数中,list1甚至不是全局名称。它是函数的一个参数的名称,因此其作用类似于函数的局部变量名。

短期课程:停止思考名字,而是从物体的角度思考。名称从不在进程之间共享。

相关内容

  • 没有找到相关文章

最新更新