2014-02-21 128 views
34

我完全混淆subprocess.call(),subprocess.Popen(),subprocess.check_call()阻塞和不阻塞子進程調用

哪個阻塞,哪個不是?

我的意思是說,如果我使用subprocess.Popen()父進程是否等待子進程到return/exit,然後繼續執行。

shell=True如何影響這些調用?

+0

您是否嘗試過'subprocess.call([cmd,params,&])'? –

回答

52

Popen是非阻塞的。 callcheck_call正在阻止。 您可以通過調用waitcommunicate方法來製作Popen實例塊。

如果你在the source code看,你會看到call調用Popen(...).wait(),這就是爲什麼它阻止。 check_call調用call,這也是它阻塞的原因。

嚴格來說,shell=True正交於阻塞問題。但是,shell=True會導致Python執行一個shell,然後在shell中運行該命令。如果您使用阻止呼叫,當shell完成時,呼叫將返回。由於shell可能會產生一個子進程來運行命令,因此shell可能會在產生的子進程之前完成。例如,

import subprocess 
import time 

proc = subprocess.Popen('ls -lRa /', shell=True) 
time.sleep(3) 
proc.terminate() 
proc.wait() 

這裏生成了兩個進程:Popen生成一個運行shell的子進程。殼又產生運行ls的子進程。 proc.terminate()殺死shell,但仍運行ls的子進程。 (即使python腳本已經結束,也會顯示出豐富的輸出,準備好用pkill ls來殺死ls。)

+4

['start_new_session = True'或其類似物](http://stackoverflow.com/a/13256908/4279)可立即終止整個進程樹。請參閱[如何終止使用shell = True啓動的python子進程](http://stackoverflow.com/q/4789837/4279) – jfs

+0

謝謝你的回答幫助了我很多。附: 'proc = subprocess.Popen(['/ run_python.py','-n','10'],shell = True)'不同於'proc = subprocess.Popen(「run_python.py -n 10」, shell = True)'只有最後一個工作,如果命令是建立在python腳本之上的。 – dotslash

+2

@dotslash:'shell = True'如果命令來自用戶輸入,可能是[安全隱患](https://docs.python.org/2/library/subprocess.html#using-the-subprocess-module) 。所以如果可能的話最好使用'shell = False'。用'shell = False',在列表中提供命令及其參數:'proc = subprocess.Popen(['/ run_python.py','-n','10'],shell = False)'。 – unutbu