如何终止与外壳推出了蟒蛇子=真

问题描述:

我启动用下面的命令一个子:如何终止与外壳推出了蟒蛇子=真

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

使用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 

shell=True shell是子进程,并且这些命令是它的子进程。因此,任何SIGTERMSIGKILL都会杀死shell而不是它的子进程,我不记得一个好办法。 我能想到的最好的方法是使用shell=False,否则当你杀死父shell进程时,它会留下一个不存在的shell进程。

正如西说,外壳是孩子,所以信号被截获它 - 我已经找到了最好的方法是使用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

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()应该工作。

我不知道这对你的管道有什么影响。

我能做到这一点使用

from subprocess import Popen 

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

它杀死了cmd.exe,而我给了命令程序。

(在Windows上)

如果你可以使用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) 

这个答案都不为我工作因此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进程,并且终止了进程。