2013-04-03 39 views
11

是否有一种简单的方法可以使用多处理来做到这一点?Python多处理 - 将类方法应用于对象列表

for sim in sim_list: 
    sim.run() 

其中sim_list的元素是“模拟”对象和运行()是模拟类修改对象的属性的方法。例如:

class simulation: 
    __init__(self): 
    self.state['done']=False 
    self.cmd="program" 
def run(self): 
    subprocess.call(self.cmd) 
    self.state['done']=True 

sim_list中的所有sim都是独立的,所以策略不必是线程安全的。

我尝试了以下内容,这显然有缺陷,因为参数是通过深层复制传递的,并且未就地进行修改。

from multiprocessing import Process 

for sim in sim_list: 
    b = Process(target=simulation.run, args=[sim]) 
    b.start() 
    b.join() 
+3

你不想在循环中加入()你的进程,或者你将一个接一个地运行它们,而不是并行运行它们。要回答您的问题,您可以在启动进程时发送multiprocessing.Queue对象,然后在完成时将自己放入队列中。 –

+0

好的关于join()的评论。关于Queue的使用,我不确定这应该如何工作。无论如何,我的SIM卡对象是否会通过深层复制传递? – calys

+0

@calys在windows上,你会得到一个'PicklingError',因为你试图腌制一个方法,在UNIX上没有“deepcopy”,简单地说每个进程都获得整个地址空间的完美副本。您必须通过某些明确的进程间通信来替换实例中的状态更改。 – Bakuriu

回答

11

一种方法做你想做的是让你的计算类(simulation你的情况)是Process一个子类。当正确初始化时,这个类的实例将在单独的进程中运行,并且您可以像列表中那样从列表中引发一组它们。

下面是一个例子,建立在你上面写道:

import multiprocessing 
import os 
import random 

class simulation(multiprocessing.Process): 
    def __init__(self, name): 
     # must call this before anything else 
     multiprocessing.Process.__init__(self) 

     # then any other initialization 
     self.name = name 
     self.number = 0.0 
     sys.stdout.write('[%s] created: %f\n' % (self.name, self.number)) 

    def run(self): 
     sys.stdout.write('[%s] running ... process id: %s\n' 
         % (self.name, os.getpid())) 

     self.number = random.uniform(0.0, 10.0) 
     sys.stdout.write('[%s] completed: %f\n' % (self.name, self.number)) 

接下来,只要对象的列表,并开始每一个与一个循环:

sim_list = [] 
sim_list.append(simulation('foo')) 
sim_list.append(simulation('bar')) 

for sim in sim_list: 
    sim.start() 

当你运行这个你应该看到每个对象在自己的进程中运行。不要忘记在你的课程初始化之前把Process.__init__(self)作为第一件事,在别的之前。

很明显,我没有在这个例子中包含任何进程间通信;如果您的情况需要,您必须补充说明(从您的问题中不清楚您是否需要它)。

这种方法对我来说效果很好,而且我没有意识到任何缺点。如果有人知道我忽略的隐患,请告诉我。

我希望这会有所帮助。

+1

非常感谢。它的工作原理:) – calys

+0

很好的答案,谢谢 –