Как работает multiprocessing.Manager () в python?

У меня есть забота о multiprocessing.Manager () в python, вот пример,

import multiprocessing def f(ns): ns.x *=10 ns.y *= 10 if __name__ == '__main__': manager = multiprocessing.Manager() ns = manager.Namespace() ns.x = 1 ns.y = 2 print 'before', ns p = multiprocessing.Process(target=f, args=(ns,)) p.start() p.join() print 'after', ns 

и выход,

  • Время печати в скрипте многопроцессорности Python возвращает отрицательное время
  • Получить код завершения процессов, запущенных с помощью многопроцессорной обработки. Pool.map
  • Использование multiprocessing.Manager.list вместо реального списка позволяет рассчитать возраст
  • Пул многопроцессорности Python висит при соединении?
  • Совместное использование очереди результатов между несколькими процессами
  • Ненадежная производительность загрузки файлов с S3 с помощью boto и многопроцессорной обработки.
  •  before Namespace(x=1, y=2) after Namespace(x=10, y=20) 

    До сих пор это работало так, как я ожидал, тогда я изменил код, как это,

     import multiprocessing def f(ns): ns.x.append(10) ns.y.append(10) if __name__ == '__main__': manager = multiprocessing.Manager() ns = manager.Namespace() ns.x = [] ns.y = [] print 'before', ns p = multiprocessing.Process(target=f, args=(ns,)) p.start() p.join() print 'after', ns 

    теперь, выход,

     before Namespace(x=[], y=[]) after Namespace(x=[], y=[]) 

    Это меня смутило, почему список не изменился, как и ожидалось? кто-нибудь может помочь мне разобраться в том, что произошло? Заранее спасибо!

  • Как изменить каталоги с помощью Paramiko?
  • Ошибка EOF Python в raw_input ()
  • Почему я не могу повторить цикл «for» для csv.Reader? (Python)
  • Любая причина не использовать «+» для объединения двух строк?
  • Структура данных для сопоставлений 1: 1 в python?
  • установка cx_Freeze на python в окнах
  • 2 Solutions collect form web for “Как работает multiprocessing.Manager () в python?”

    Примечание. Этот ответ может быть неточным для Python 3.6+. Я обновлю его, когда у меня будет время для расследования. (Или не стесняйтесь редактировать!)


    Прокси-объекты менеджера не могут распространять изменения, внесенные в изменяемые объекты внутри контейнера. Другими словами, если у вас есть объект manager.list() , любые изменения в управляемом списке распространяются на все остальные процессы. Но если у вас есть список внутри этого списка, любые изменения во внутреннем списке не распространяются, потому что менеджер не может обнаружить изменения.

    Чтобы распространять изменения, вам необходимо напрямую изменить объект manager.list() , как указано в примечании.

    Например, рассмотрим следующий код и его вывод:

     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 ls_2 = ls[2] ls_2[0] += 1 ls[2] = ls_2 di[0] += 1 di[1][0] += 1 di_2 = di[2] di_2[0] += 1 di[2] = di_2 if __name__ == '__main__': manager = multiprocessing.Manager() ns = manager.Namespace() ns.x = 1 ns.y = [1] ns.z = [1] ls = manager.list([1, [1], [1]]) di = manager.dict({0: 1, 1: [1], 2:[1]}) print 'before', ns, ls, di p = multiprocessing.Process(target=f, args=(ns, ls, di)) p.start() p.join() print 'after', ns, ls, di 

    Вывод:

     before Namespace(x=1, y=[1], z=[1]) [1, [1], [1]] {0: 1, 1: [1], 2: [1]} after Namespace(x=2, y=[1], z=[2]) [2, [1], [2]] {0: 2, 1: [1], 2: [2]} 

    Как вы можете видеть, когда новое значение присваивается непосредственно управляемому контейнеру, оно изменяется; когда он присваивается изменяемому контейнеру в управляемом контейнере, он не изменяется; но если измененный контейнер затем переназначается в управляемый контейнер, он снова изменяется.

    ns – экземпляр NamespaceProxy. Эти объекты имеют специальные __getattr__ , __setattr__ и __delattr__ которые позволяют передавать значения между процессами. Чтобы воспользоваться этим механизмом при изменении значения, вы должны запустить __setattr__ .

     ns.x.append(10) 

    вызывает ns.__getattr__ для вызова ns.x , но это не вызывает ns.__setattr__ должен быть вызван.

    Чтобы исправить это, вы должны использовать ns.x = ...

     def f(ns): tmp = ns.x # retrieve the shared value tmp.append(10) ns.x = tmp # set the shared value 
    Python - лучший язык программирования в мире.