Python Multiprocessing.Manager()具有全局变量的奇怪行为
我对Python Multiprocessing.Manager()具有全局变量的奇怪行为,python,multithreading,global-variables,python-multiprocessing,Python,Multithreading,Global Variables,Python Multiprocessing,我对multiprocessing.Manager类有一个问题,当Manager对象是全局变量时,该类的行为非常奇怪 代码1: 导入多处理 从多处理导入管理器 经理=经理() list1=manager.list(范围(4)) dict1=manager.dict({“d”:1,“f”:2}) def process1(列表1,dict1): 打印“进程1” dict1[“3”]=123 列表1.追加(10) def run(): 打印“开始” 全球清单1 全球宣言1 打印“列表1”,列表1 打
multiprocessing.Manager
类有一个问题,当Manager对象是全局变量时,该类的行为非常奇怪
代码1:
导入多处理
从多处理导入管理器
经理=经理()
list1=manager.list(范围(4))
dict1=manager.dict({“d”:1,“f”:2})
def process1(列表1,dict1):
打印“进程1”
dict1[“3”]=123
列表1.追加(10)
def run():
打印“开始”
全球清单1
全球宣言1
打印“列表1”,列表1
打印“dict1”,dict1
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
打印“开始”
j=multiprocessing.Process(target=process1,args=(list1,dict1))
j、 开始()
j、 加入
运行()
输出1:
开始
过程1
开始
清单1[0,1,2,3,10]
dict1{'3':123,'d':1,'f':2}
好的,这意味着全局变量̀list1
和dict1
已被process1
修改
问题是,当我尝试替换list1
或dict1
时,它不起作用
代码2:
导入多处理
从多处理导入管理器
经理=经理()
list1=manager.list(范围(4))
dict1=manager.dict({“d”:1,“f”:2})
def process1(列表1,dict1):
打印“进程1”
dict1[“3”]=123
list1=manager.list(范围(100104))
def run():
打印“开始”
全球清单1
全球宣言1
打印“列表1”,列表1
打印“dict1”,dict1
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
打印“开始”
j=multiprocessing.Process(target=process1,args=(list1,dict1))
j、 开始()
j、 加入
运行()
输出2:
开始
过程1
开始
清单1[0,1,2,3]
dict1{'3':123,'d':1,'f':2}
知道它为什么返回初始列表
[0,1,2,3]
而不是[100,101,102,103]
吗?当一个管理器.list
对象跨进程共享时,绑定到该对象的名称根本不会共享,即使在所有进程中使用相同的名称也不会共享global
表示在运行模块的进程中,在整个模块中都可以看到相同的绑定(除非在某些局部范围中被重写);仅仅因为导入了多处理
,它就神奇地意味着更多;-)
具体来说,主进程中的名称list1
与辅助进程中的名称list1
无关。它们之间唯一的关系是,两个名称最初恰好绑定到Manager.list
的一个共享实例。这通常是你想从他们那里得到的。在这两个过程中,将名称list1
重新绑定到其他对象不会对名称list1
在任何其他过程中绑定到的对象产生任何影响
因此,在第二个示例中,在工作进程中,名称list1
将(重新)绑定到一个新的manager.list(范围(100104))
实例。这对主进程中namelist1
的绑定没有任何影响。工作进程也没有任何可能的方法来更改任何其他进程中任何名称的绑定——如果发生这种情况,那将是一场噩梦
不过,您可以更改共享对象值。但你似乎已经知道了。例如,做
list1[:] = range(100,104)
相反,不更改任何绑定,而是替换共享的Manager.list
实例的整个内容(因此主进程也会看到新的列表内容,不是因为名称相同,而是因为两个名称都绑定到同一个对象)
顺便说一下,请注意,在process1
函数中,list1
甚至不是全局名称。它是函数参数之一的名称,因此其作用类似于函数局部变量名
短期课程:停止思考名称,而是从对象的角度思考。进程之间永远不会共享名称