Обмен данными между процессами Manager

задняя часть Python Linux Windows

Эта статья была впервые опубликована вЗнай почти
Эта статья разделена на следующие части

  • введение
  • Менеджер начального тестирования
  • Меры предосторожности
  • распределенный процесс

введение

В мультипроцессе каждый процесс имеет свою собственную копию переменной, поэтому переменная в основном процессе передается другим процессам для модификации, а полученный результат все еще сохраняется в этом процессе.Эта переменная в основном процессе фактически эквивалентна не модифицируется. . Чтобы синхронизировать изменения, внесенные другими процессами в основной процесс, необходимо создать переменные, которые могут использоваться несколькими процессами.

например

from multiprocessing import Process
def f1(x, l):
x += 1
l.append(2)
def f2(x, l):
x -= 2
l.append(3)
if __name__ == '__main__':
x = 0
l = [1]
p1 = Process(target=f1, args=(x, l))
p2 = Process(target=f2, args=(x, l))
p1.start()
p2.start()
p1.join()
p2.join()
print(x, l)

Результат бега есть

0 [1]

x lНи один из них не был изменен, потому что они были изменены в других процессах.

Менеджер начального тестирования

Мы упоминали некоторые методы обмена данными между процессами в предыдущей статье, такие какQueue pipe value,ноmultiprocessingМодули также обеспечивают более продвинутую инкапсуляцию, готовые к использованию.ManagerЧтобы создать переменные для совместного использования между процессами, давайте посмотрим непосредственно на следующий пример.

from multiprocessing import Process, Manager
def f1(ns, l):
ns.x += 1
l.append(2)
def f2(ns, l):
ns.x -= 2
l.append(3)
if __name__ == '__main__':
manager = Manager()
ns = manager.Namespace()
l = manager.list([1])
ns.x = 0
p1 = Process(target=f1, args=(ns, l))
p2 = Process(target=f2, args=(ns, l))
p1.start()
p2.start()
p1.join()
p2.join()
print(ns, l)

Результат выглядит следующим образом

Namespace(x=-1) [1, 2, 3]

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

managerДля других типов создания см.Официальный сайт

Меры предосторожности

иногда используетсяmanagerВсе равно будет обнаружено, что переменная не была изменена другими процессами, такими как использованиеmanager.Namespace()Создать модификацию списка недопустимо, или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 ls diПосмотрите на три части отдельно, каждая часть первая и третья изменились, вторая не изменилась, читатель может почувствовать разницу между ними

распределенный процесс

Обычный дистрибутив должен работать на двух компьютерах, но у меня только один компьютер, поэтому я открыл две командные строки, запустил два файла и смоделировал распределенную операцию.

Следующее создаст два файла: master.py и task1.py.

  • Файл master.py создает список, этот файл отвечает за нахождение в спискеappendданные. Это бесполезно, потому что есть только один процессProcess, но выполняется линейно
  • Файл task1.py должен выполнять список в файле master.py.pop

Идея реализации заключается в следующем

  • Список в файле master.py создается нормально иwhile TrueЦикл продолжает добавлять элементы
  • master.py, в котором вы хотите установить пароль учетной записи, этот список будет выставлен переменной
  • Файл task1.py должен подключиться к файлу master.py через пароль учетной записи и извлечь переменную списка.

Содержимое файла master.py выглядит следующим образом.

import random, time
from multiprocessing.managers import BaseManager as bm
l = []
def return_l():
return l
if __name__ == '__main__':
# 三步固定这么做即可
bm.register('get_l', callable = return_l)
m = bm(address = ('127.0.0.1', 5000), authkey = b'abc')
m.start()
new_l = m.get_l()
while True:
new = random.randint(0, 100)
new_l.append(new)
print('produce {} now all {}'.format(new, new_l))
time.sleep(2 * random.random())
m.shutdown()
print('master exit')

Содержимое файла task1.py выглядит следующим образом.

import random
import time
from multiprocessing.managers import BaseManager as bm
if __name__ == '__main__':
bm.register('get_l')
m = bm(address = ('127.0.0.1', 5000), authkey = b'abc')
m.connect()
l = m.get_l()
while True:
print('drop {}'.format(l.pop()))
time.sleep(3 * random.random())

На самом деле, глядя на приведенный выше код в сочетании с представленными ранее идеями, вы сможете понять, как устроен дистрибутив.Давайте поговорим о том, как работать.

После сохранения этих двух файлов откройте cmd в расположении этих двух файлов соответственно. Ниже я буду называть их cmdm и cmdt соответственно.

Введите в cmdm

python master.py

В это время вы обнаружите, что программа начинает работать, и в списке появляется все больше и больше элементов. Затем введите в cmdt

python task1.py

Вы обнаружите, что элементы списка в cmdm начнут уменьшаться.

Этот процесс фактически запускает два файла, пока master.py запускается первым. Запуск двух файлов фактически эквивалентен открытию двух процессов, а открытие их на двух компьютерах — то же самое.

Примечание. Приведенный выше код работает в системе Windows. Распределенные процессы в Linux могут относиться кЭта статья г-на Ляо Сюэфэна, код в этой статье не может работать под windows, перепишите его в ссылку на версию под windowsэта статья

Добро пожаловать, чтобы обратить внимание на мою колонку знаний

Главная страница колонки:программирование на питоне

Каталог столбцов:содержание

Примечания к выпуску:Примечания к выпуску программного обеспечения и пакетов