设置从multiprocessing.Process继承的Python类的值的问题

时间:2013-05-15 15:29:33

标签: python process multiprocessing local-variables

为什么这段代码

import multiprocessing
import time

class Bot(multiprocessing.Process):
    def __init__(self):        
        self.val = 0
        multiprocessing.Process.__init__(self)

    def setVal(self):
        self.val = 99

    def run(self):        
        while True:            
            print 'IN: ', self.val
            time.sleep(2)

if __name__ == '__main__':  
    bot = Bot()
    bot.start()
    bot.setVal()
    while True:
        print 'OUT: ', bot.val
        time.sleep(2)            

给出以下输出?

OUT:  99
IN:  0
OUT:  99
IN:  0
OUT:  99
IN:  0
OUT:  99
IN:  0
OUT:  99
IN:  0
OUT:  99
IN:  0
...

你可能猜到我希望得到所有99,IN和OUT。但我不。为什么?我错过了什么?

3 个答案:

答案 0 :(得分:2)

一旦你在对象上调用start(),该对象内的东西就会在一个单独的进程中运行,并且使用该类的方法与它进行“通信”并不是最好的方法。您需要做的是称为进程间通信(简称IPC),并且有正确的机制来正确执行。

对于Python的multiprocessing模块,有两种在进程之间进行通信的机制:PipeQueue。我建议调查那些(例如here)。

要在示例中使用Pipe机制,您可以这样做(只是一个快速说明):

class Bot(multiprocessing.Process):
    def __init__(self, pipe):
        multiprocessing.Process.__init__(self)
        self.val = 0
        self.ipcPipe = pipe

    def run(self):
        while True: 
            newData = self.ipcPipe.recv()
            self.val = newData[0]
            print 'IN: ', self.val
            self.ipcPipe.send([self.val])
            time.sleep(2)

if __name__ == '__main__': 
    parent_conn, child_conn = multiprocessing.Pipe()
    bot = Bot(child_conn)
    bot.start()
    value = 0
    while True:
        value += 1
        parent_conn.send([value])
        outVal = parent_conn.recv()
        print 'OUT: ', outVal[0]
        time.sleep(2)

看看这里做了什么:我们创建Pipe的父和子“结束”,并让孩子结束你的对象。然后,从父进程使用send()向对象传递新值,并使用recv()获取更新后的值。同样在您的对象内部(请记住一个单独的进程),您反过来在管道的另一端使用send()recv()来与父进程通信。

此外,我建议您在进行任何其他初始化之前在类Process.__init__(self)方法中调用__init__。由于你是从Process继承而来的,所以在你在自己的课堂上做任何事情之前,确保所有过程中的所有东西都被正确初始化是个好主意。

希望这有帮助。

答案 1 :(得分:1)

问题在于,一旦启动第二个流程,就会从两个不同的流程进行打印。

父进程具有bot的原始实例,然后将值设置为99.父进程正在打印OUT,这就是您打印值99的原因。

(新)子进程以从bot对象复制的状态开始,就像调用多处理方法start()时一样。因此,它的状态为0.你永远不会在子进程中调用setVal,因此它的值保持为0,IN打印出0。

如果要在父进程和子进程之间共享这样的状态信息,请阅读: http://docs.python.org/2/library/multiprocessing.html#sharing-state-between-processes

答案 2 :(得分:0)

bot = Bot() # creates a bot object in this process
bot.start() # creates an other process and creates a bot object there

这是两个不同的对象。 如果您想了解如何在两个进程之间共享状态:http://docs.python.org/2/library/multiprocessing.html#namespace-objects

或者DMH提出的管道: http://docs.python.org/2/library/multiprocessing.html#sharing-state-between-processes