Ответ 1
Прокси-объекты менеджера не могут распространять изменения, внесенные в (неуправляемые) изменяемые объекты внутри контейнера. Другими словами, если у вас есть объект 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]
Как вы можете видеть, когда новое значение присваивается непосредственно управляемому контейнеру, оно изменяется; когда он присваивается изменяемому контейнеру в управляемом контейнере, он не изменяется; но если измененный контейнер затем переназначается в управляемый контейнер, он снова изменяется. Использование вложенного управляемого контейнера также работает, обнаруживая изменения непосредственно, не назначая обратно родительскому контейнеру.