Прокси-объекты диспетчера не могут распространять изменения, внесенные в (неуправляемые) изменяемые объекты внутри контейнера. Другими словами, если у вас есть объект manager.list()
, любые изменения в самом управляемом списке распространяются на все другие процессы. Но если у вас есть обычный список Python внутри этого списка, любые изменения во внутреннем списке не распространяются, потому что менеджер не может обнаружить это изменение.
Чтобы распространить изменения, вы должны использовать manager.list()
объекты для вложенных списков (требуется Python 3.6 или новее ), или вам нужно изменить объект manager.list()
напрямую (см. примечание на manager.list
в Python 3.5 или старше ).
Например, рассмотрим следующий код и его вывод:
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 # unmanaged, not assigned back
ls_2 = ls[2] # unmanaged...
ls_2[0] += 1
ls[2] = ls_2 # ... but assigned back
ls[3][0] += 1 # managed, direct manipulation
di[0] += 1
di[1][0] += 1 # unmanaged, not assigned back
di_2 = di[2] # unmanaged...
di_2[0] += 1
di[2] = di_2 # ... but assigned back
di[3][0] += 1 # managed, direct manipulation
if __name__ == '__main__':
manager = multiprocessing.Manager()
ns = manager.Namespace()
ns.x = 1
ns.y = [1]
ns.z = [1]
ls = manager.list([1, [1], [1], manager.list([1])])
di = manager.dict({0: 1, 1: [1], 2: [1], 3: manager.list([1])})
print('before', ns, ls, ls[2], di, di[2], sep='\n')
p = multiprocessing.Process(target=f, args=(ns, ls, di))
p.start()
p.join()
print('after', ns, ls, ls[2], di, di[2], sep='\n')
Выход:
before
Namespace(x=1, y=[1], z=[1])
[1, [1], [1], <ListProxy object, typeid 'list' at 0x10b8c4630>]
[1]
{0: 1, 1: [1], 2: [1], 3: <ListProxy object, typeid 'list' at 0x10b8c4978>}
[1]
after
Namespace(x=2, y=[1], z=[2])
[2, [1], [2], <ListProxy object, typeid 'list' at 0x10b8c4630>]
[2]
{0: 2, 1: [1], 2: [2], 3: <ListProxy object, typeid 'list' at 0x10b8c4978>}
[2]
Как видите, когда новое значение присваивается непосредственно управляемому контейнеру, оно изменяется; когда он назначается изменяемому контейнеру в управляемом контейнере, он не изменяется; но если изменяемый контейнер затем переназначается на управляемый контейнер, он снова изменяется. Использование вложенного управляемого контейнера также работает, обнаруживая изменения напрямую, без необходимости присваивания родительскому контейнеру.