问题
Why this code
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)
gives following output?
OUT: 99
IN: 0
OUT: 99
IN: 0
OUT: 99
IN: 0
OUT: 99
IN: 0
OUT: 99
IN: 0
OUT: 99
IN: 0
...
As you may guess i expect to get all 99, IN and OUT. But i do not. Why? What am i missing?
回答1:
The problem is that once you start the second process, you are printing from 2 different processes.
The parent process has the original instance of bot, with the value then set to 99. The parent process is printing OUT which is why you get the value 99 printed.
The (new) subprocess starts with state copied from the bot object as it was when you called the multiprocessing method start()
. Because of this, it has a state of 0. You never call setVal in the subprocess and so it's value remains 0, and the IN prints print 0.
If you want to share state information like this between the parent process and the subprocess, have a read of this: http://docs.python.org/2/library/multiprocessing.html#sharing-state-between-processes
回答2:
Once you've called start()
on your object, the stuff inside that object is running in a separate process, and using methods of that class to "communicate" with it are not really the best way. What you need to do is called inter-process communication (IPC for short) and there is special machinery for doing it correctly.
For Python's multiprocessing
module there are two mechanisms for communicating between processes: Pipe
and Queue
. I would suggest looking into those (e.g. here).
To use the Pipe
mechanism in your example, you might do it this way (just a quick illustration) :
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)
See what's been done here: We create parent and child "ends" of the Pipe
, and give the child end to your object. Then from the parent process you use send()
to communicate a new value to the object, and recv()
to get an updated value back. Likewise inside your object (a separate process, remember) you conversely use send()
and recv()
on the pipe's other end to communicate with the parent process.
Also, I would recommend calling Process.__init__(self)
in your class __init__
method before doing any other initialization. Since you're inheriting from Process
it's a good idea to make sure all the process-y stuff under the hood gets initialized correctly before you do anything in your own class.
Hope this helps.
回答3:
bot = Bot() # creates a bot object in this process
bot.start() # creates an other process and creates a bot object there
These are two different objects. If you want to have a look at how to share state between two processes: http://docs.python.org/2/library/multiprocessing.html#namespace-objects
Or at the pipes also proposed by DMH: http://docs.python.org/2/library/multiprocessing.html#sharing-state-between-processes
来源:https://stackoverflow.com/questions/16569175/issue-with-setting-value-for-python-class-inherited-from-multiprocessing-process