我遇到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}
好的,这意味着̀list1
修改了全局变量dict1
和process1
。
问题在于,当我尝试替换list1
或dict1
时,它无法正常工作!
代码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]
?
答案 0 :(得分:0)
虽然跨进程共享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
无论如何都不是全局名称。它是函数参数之一的名称,因此就像函数本地变量名一样。
短期课程:不再考虑名字,而是考虑对象。名称永远不会在进程间共享。