在下面的代码中,如何使Starter
对象能够读取gen.vals
? 似乎创建了一个不同的对象,其状态被更新,但Starter
永远不知道它。此外,该解决方案如何适用于self.vals
字典或任何其他类型的对象?
import multiprocessing
import time
class Generator(multiprocessing.Process):
def __init__(self):
self.vals = []
super(Generator, self).__init__()
def run(self):
i = 0
while True:
time.sleep(1)
self.vals.append(i)
print 'In Generator ', self.vals # prints growing list
i += 1
class Starter():
def do_stuff(self):
gen = Generator()
gen.start()
while True:
print 'In Starter ', gen.vals # prints empty list
time.sleep(1)
if __name__ == '__main__':
starter = Starter()
starter.do_stuff()
输出:
In Starter []
In Starter []
In Generator [0]
In Starter []
In Generator [0, 1]
In Starter []
In Generator [0, 1, 2]
In Starter []
In Generator [0, 1, 2, 3]
In Starter []
In Generator [0, 1, 2, 3, 4]
In Starter []
In Generator [0, 1, 2, 3, 4, 5]
In Starter []
In Generator [0, 1, 2, 3, 4, 5, 6]
In Starter []
In Generator [0, 1, 2, 3, 4, 5, 6, 7]
当你启动一个进程时,它基本上在一个完整的独立上下文中执行(这是对正在发生的事情的简要解释),所以没有共享内存可言,因此无论你的run()
方法做什么,都不会真正反映在你的主进程中 - Python 从中生成/分叉一个全新的进程,在那里实例化你的Generator
并调用它的run()
方法以及对另一个实例的状态的任何更改在不同的过程中留在那里。
如果要传递数据,则需要使用一些多处理感知结构,这些结构本质上将序列化/反序列化不同进程之间的数据,并来回传达更改。例如:
import multiprocessing
import time
class Generator(multiprocessing.Process):
def __init__(self):
self._vals = [] # keeps the internal state
self.vals = multiprocessing.Queue() # a queue for the exchange
super(Generator, self).__init__()
def run(self):
i = 0
while True:
time.sleep(1)
self._vals.append(i) # update the internal state
print('In Generator ', self._vals) # prints growing list
self.vals.put(self._vals) # add it to the queue
i += 1
class Starter():
def do_stuff(self):
gen = Generator()
gen.start()
while True:
print('In Starter ', gen.vals.get()) # print what's in the queue
time.sleep(1)
if __name__ == '__main__':
starter = Starter()
starter.do_stuff()
将打印出来:
在发电机中 [0] 在启动器 [0] 在发电机 [0, 1] 中 在启动器 [0, 1] 中 在发电机 [0, 1, 2] 中 在启动器 [0, 1, 2] 中 在生成器 [0, 1, 2, 3] 中 在启动器 [0, 1, 2, 3] 中 等。
如果要进行更复杂/半并发的数据修改或处理更结构化的数据,请检查multiprocessing.Manager
支持的结构。当然,对于非常复杂的东西,我总是建议使用像 Redis 这样的内存数据库作为进程间数据交换的一种方式。或者,如果您更喜欢自己进行微观管理,ØMQ始终是一个不错的选择。