Многопроцессорный процесс, очередь и объекты - PullRequest
0 голосов
/ 02 февраля 2020

Я новичок в Python multiprocessing и просто не могу понять, как работает этот фрагмент кода:

from multiprocessing import Process, Queue


class C:
    dic = {}


def put_in_queue(q, v):
    c = C()
    print("before update:", c.dic)
    c.dic.update({0: v})
    print("after update", c.dic)
    q.put(c)


def main():
    queue = Queue()
    put_in_queue(queue, 0)
    c = queue.get()
    print("get from queue dic:", c.dic)

    p = Process(target=put_in_queue, args=(queue, 1))
    p.start()
    p.join()
    c = queue.get()
    print("get from queue modified by process dic:", c.dic)


if __name__ == '__main__':
    main()

Его вывод следующий:

before update: {}
after update {0: 0}
get from queue dic: {0: 0}
before update: {0: 0}
after update {0: 1}
get from queue modified by process dic: {0: 0}

Есть два основных вопроса, на которые я не могу ответить:

  1. Почему обновление словаря, сделанное процессом, не распространяется обратно на основной процесс даже если измененный объект должен быть пропущен через очередь.

  2. Почему вновь созданный объект в процессе, похоже, уже имеет измененное значение для dict, даже если он только что создан и обновление на нем еще не сделано?

Я думаю, что это связано с передачей пользовательского объекта вместо простого типа.

Может быть, это довольно глупый вопрос, но я просто еще не понимаю его. Некоторое объяснение или помощь будут очень признательны.

1 Ответ

0 голосов
/ 02 февраля 2020

Я думаю, что ваши подвопросы возникли из-за неправильного понимания того, как классы работают в Python. То, как вы определили класс C:

class C:
    dic = {}

, означает, что все экземпляры класса будут использовать один и тот же атрибут dic, потому что это class, не экземпляр, атрибут при объявлении таким образом.

Чтобы изменить его на атрибут экземпляр , вам нужно сделать что-то вроде этого:

class C:
    def __init__(self):
        self.dic = {}

Это дает каждому экземпляр своего собственного независимого атрибута (на который не будут влиять изменения, внесенные в него через другие экземпляры, что и происходит, когда он выполняется другим способом).

С этим изменением вывод из вашего сценария становится:

before update: {}
after update {0: 0}
get from queue dic: {0: 0}
before update: {}
after update {0: 1}
get from queue modified by process dic: {0: 1}
...