2011-01-25 39 views
207

我啓動用下面的命令一個子:如何終止與外殼推出了蟒蛇子=真

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 

但是,當我嘗試使用殺:

p.terminate() 

p.kill() 

該命令一直在後臺運行,所以我想知道如何才能真正終止進程秒。

需要注意的是,當我運行命令:

p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) 

發出p.terminate()當它成功地終止。

+0

你的`cmd`看起來像什麼?它可能包含一個觸發幾個進程啓動的命令。所以目前還不清楚你談論的是哪一個流程。 – 2014-11-27 15:47:49

+2

相關:[Python:如何殺死父母死亡時的子進程?](http://stackoverflow.com/q/23434842/4279) – jfs 2015-01-23 15:08:43

回答

287

使用process group以便能夠向組中的所有進程發送信號。爲此,你應該附加一個session id到衍生/子進程的父進程,這是你的情況下的shell。這將使其成爲流程的組長。所以現在,當一個信號被髮送給過程組領導者時,它會被傳送給這個組的所有子過程。

下面的代碼:

import os 
import signal 
import subprocess 

# The os.setsid() is passed in the argument preexec_fn so 
# it's run after the fork() and before exec() to run the shell. 
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
         shell=True, preexec_fn=os.setsid) 

os.killpg(os.getpgid(pro.pid), signal.SIGTERM) # Send the signal to all the process groups 
5

shell=True shell是子進程,並且這些命令是它的子進程。因此,任何SIGTERMSIGKILL都會殺死shell而不是它的子進程,我不記得一個好辦法。 我能想到的最好的方法是使用shell=False,否則當你殺死父shell進程時,它會留下一個不存在的shell進程。

4

正如西說,外殼是孩子,所以信號被截獲它 - 我已經找到了最好的方法是使用shell =假,並使用shlex命令行拆分:

if isinstance(command, unicode): 
    cmd = command.encode('utf8') 
args = shlex.split(cmd) 

p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 

然後p.kill()和p.terminate()應該如何工作。

+1

在我的情況下,它並沒有真正的幫助,因爲cmd是「CD路徑&& zsync等等「。所以這實際上使命令失敗! – user175259 2011-01-25 23:00:31

+4

使用絕對路徑而不是更改目錄...可選擇os.chdir(...)到該目錄... – 2011-01-26 06:27:25

+0

可以更改子進程的工作目錄。只需將`cwd`參數傳遞給[`Popen`](https://docs.python.org/2/library/subprocess.html#subprocess.Popen)。 – 2015-08-17 01:22:35

66
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 
p.kill() 

p.kill()最終殺死shell進程和cmd仍在運行。

我發現了一個方便的修正這個由:

p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True) 

這將導致的而不是外殼啓動子進程,不被殺CMD繼承shell進程。那麼p.pid將是你的cmd進程的id。

p.kill()應該工作。

我不知道這對你的管道有什麼影響。

16

我能做到這一點使用

from subprocess import Popen 

process = Popen(command, shell=True) 
Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid)) 

它殺死了cmd.exe,而我給了命令程序。

(在Windows上)

30

如果你可以使用psutil,那麼這個完美的作品:

import subprocess 

import psutil 


def kill(proc_pid): 
    process = psutil.Process(proc_pid) 
    for proc in process.children(recursive=True): 
     proc.kill() 
    process.kill() 


proc = subprocess.Popen(["infinite_app", "param"], shell=True) 
try: 
    proc.wait(timeout=3) 
except subprocess.TimeoutExpired: 
    kill(proc.pid) 
0

這個答案都不爲我工作因此Im留下沒有工作的代碼。在我的情況下,即使在使用.kill()殺死進程並獲取.poll()返回代碼之後,進程仍未終止。

subprocess.Popendocumentation

「......爲了清理正確性能良好的應用程序應該殺子進程,並完成通信......」

proc = subprocess.Popen(...) 
try: 
    outs, errs = proc.communicate(timeout=15) 
except TimeoutExpired: 
    proc.kill() 
    outs, errs = proc.communicate() 

在我來說,我在致電proc.kill()後錯過proc.communicate()。這清理了stdin,stdout進程,並且終止了進程。