2013-04-03 65 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

很好的答案,謝謝 –