Использование модуля многопроцессорности

Я пытаюсь использовать модуль многопроцессорности в python 2.6, но, видимо, я чего-то не понимаю. Я бы ожидал, что ниже приведенный класс добавит числа, отправленные ему с помощью add(), и вернет сумму в методе get_result(). В приведенном ниже коде печатается "0", я бы хотел, чтобы он печатал "2". Что я пропустил?

import multiprocessing

class AdderProcess(multiprocessing.Process):

    def __init__(self):
        multiprocessing.Process.__init__(self)
        self.sum = 0
        self.queue = multiprocessing.JoinableQueue(5)
        self.daemon = True
        self.start()

    def run(self):
        while True:
            number = self.queue.get()
            self.sum += number
            self.queue.task_done()

    def add(self, number):
        self.queue.put(number)

    def get_result(self):
        self.queue.join()
        return self.sum


p = AdderProcess()
p.add(1)
p.add(1)
print p.get_result()

PS. Эта проблема решена. Спасибо за ответы! Просто чтобы облегчить для читателей, здесь полная рабочая версия:

import multiprocessing

class AdderProcess(multiprocessing.Process):

    def __init__(self):
        multiprocessing.Process.__init__(self)
        self.sum = multiprocessing.Value('d', 0.0)
        self.queue = multiprocessing.JoinableQueue(5)
        self.daemon = True
        self.start()

    def run(self):
        while True:
            number = self.queue.get()
            self.sum.value += number
            self.queue.task_done()

    def add(self, number):
        self.queue.put(number)

    def get_result(self):
        self.queue.join()
        return self.sum.value

p = AdderProcess()
p.add(1)
p.add(1)
print p.get_result()

Ответы

Ответ 1

Измените self.sum = 0 на self.sum = multiprocessing.Value('d', 0.0) и используйте self.sum.value для доступа или изменения значения.

class AdderProcess(multiprocessing.Process):    
    def __init__(self):
        ...
        self.sum = multiprocessing.Value('d', 0.0) 
        ...
    def run(self):
        while True:
            number = self.queue.get()
            self.sum.value += number    # <-- use self.sum.value
            self.queue.task_done()
    def get_result(self):
        self.queue.join()
        return self.sum.value           # <-- use self.sum.value

Проблема заключается в следующем: после вызова self.start() в __init__ основной процесс отменяет дочерний процесс. Все значения копируются. Теперь есть две версии p. В основном процессе p.sum равно 0. В дочернем процессе вызывается метод run и p.sum добавляется к 2. Но когда основной процесс вызывает p.get_result(), его версия p все еще имеет p.sum равно 0. Таким образом, 0 печатается.

Если вы хотите разделить значение float между процессами, вам необходимо использовать механизм совместного доступа, например mp.Value.

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

Ответ 2

self.sum составляет 2... в этом процессе:

def run(self):
    while True:
        number = self.queue.get()
        print "got %s from queue" % number
        print "Before adding - self.sum = %d" % self.sum
        self.sum += number
        print "After adding - self.sum = %d" % self.sum
        self.queue.task_done()

[ 13:56 [email protected] ~ ]$ ./mp.py
got 1 from queue
Before adding - self.sum = 0
After adding - self.sum = 1
got 1 from queue
Before adding - self.sum = 1
After adding - self.sum = 2

См. многопроцессорность 16.3.1.4. - Совместное использование процессов между процессами о том, как сделать self.sum одинаковым в разных процессах.