2012-11-07 113 views
2

我有一組命令行工具,我想在一系列文件中並行運行。我寫了一個Python函數來包裝他們,看起來是這樣的:子進程+多處理 - 順序執行多個命令

def process_file(fn): 
    print os.getpid() 
    cmd1 = "echo "+fn 
    p = subprocess.Popen(shlex.split(cmd1)) 

    # after cmd1 finishes 
    other_python_function_to_do_something_to_file(fn) 

    cmd2 = "echo "+fn 
    p = subprocess.Popen(shlex.split(cmd2)) 
    print "finish" 

if __name__=="__main__": 
    import multiprocessing 
    p = multiprocessing.Pool() 
    for fn in files: 
     RETURN = p.apply_async(process_file,args=(fn,),kwds={some_kwds}) 

雖然這個工作,它似乎並沒有在運行多個進程;它似乎只是在串行運行(我嘗試使用Pool(5)具有相同的結果)。我錯過了什麼?是否撥打Popen「阻止」?

編輯:澄清一點。我需要cmd1,然後是一些python命令,然後是cmd2,在每個文件上依次執行。

EDIT2:從上述輸出具有圖案:

pid 
finish 
pid 
finish 
pid 
finish 

而類似呼叫,代替apply使用map(但沒有任何規定用於使kwds)看起來更像

pid 
pid 
pid 
finish 
finish 
finish 

但是,地圖調用有時(總是?)掛起後顯然成功

+0

在回答這個問題之前......爲什麼你需要'多處理器'?你可以在一個進程中創建一大堆'Popen'實例,它們就像在多個進程中創建它們一樣。 – abarnert

+0

那麼,這是我的問題的一部分(所以謝謝你幫我澄清)...我的shell命令需要連續運行(即,cmd1,cmd2,cmd3)。我希望每個*系列*在每個文件上執行。 – keflavich

+0

@abarnert是對的。只是不要在流程中調用「溝通」或「等待」 – JBernardo

回答

4

呼叫Popen「阻塞」?

編號只是創建一個subprocess.Popen立即返回,給你一個對象,你可以等待或以其他方式使用。如果你想阻止,那很簡單:

subprocess.check_call(shlex.split(cmd1)) 

同時,我不知道爲什麼你把你的ARGS連成一個字符串,然後試圖shlex他們回到列表。爲什麼不直接寫清單?

cmd1 = ["echo", fn] 
subprocess.check_call(cmd1) 

雖然這個工作,它似乎並沒有在運行多個進程;現在看來似乎只是在串行

運行什麼讓你覺得呢?鑑於每個進程都儘可能快地將兩個進程啓動到後臺,因此很難判斷它們是否並行運行。

如果您想驗證您是否從多個處理中獲得工作,則可能需要添加一些打印或日誌記錄(並在消息中添加類似os.getpid()的內容)。

同時,它看起來像你想完全複製的multiprocessing.Pool.map_async影響了一個循環的周圍multiprocessing.Pool.apply_async,只是不用積累你積攢每一個在一個叫RESULT變量的結果,然後把它扔瞭然後才能使用它。爲什麼不使用map_async

最後,您詢問multiprocessing是否適合該工作。那麼,你顯然需要一些異步:check_call(args(file1))有權阻止other_python_function_to_do_something_to_file(file1),但在同一時間不能阻止check_call(args(file2))

我可能已經使用threading,但實際上,它沒有太大的區別。即使你在一個啓動流程昂貴的平臺上,你也已經支付了這個成本,因爲整個過程都在運行N * M個子進程,所以另一個8個池不會傷害任何東西。通過在線程之間共享數據而意外創建比賽的風險很小,或者意外創建的代碼看起來像是在不同的進程之間共享數據,因爲沒有什麼可以共享。所以,無論你喜歡哪一個,都要去做。

另一種選擇是編寫事件循環。我可能真的開始自己解決這個問題,但我會後悔的,你不應該這樣做......

+0

好的,所以如果我想讓我的shell命令串行運行,'check_call'就是要走的路。那麼使用'multiprocessing'是否有意義? (re:shlex - 我的實際命令比我包含的簡單例子更復雜) – keflavich

+1

現在我明白了問題,是的,'multiprocessing'至少是一個選項。您希望在調用第一個文件的第二個進程之前阻止第一個文件的第一個進程...但是在調用第二個文件的第一個進程之前阻止該文件的第一個進程。我可能會用'threading'來做這件事(或者我甚至可能會寫一個'select'循環,然後在到達Windows的時候將我的頭撞到牆上......),但是'multiprocessing'可以正常工作。 – abarnert

+0

太好了,謝謝,這很有道理。我使用'apply'而不是'map',因爲我需要將關鍵字參數傳遞給函數。用kwarg解析器包裝或裝飾我的函數,然後使用'map_async'會更有意義嗎? – keflavich