我正在使用以下命令启动子进程:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
然而,当我尝试使用时杀死:
p.terminate()
或
p.kill()
命令一直在后台运行,所以我想知道如何才能真正终止进程。
请注意,当我使用以下命令运行命令时
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
发出p.terminate()
时会成功终止。
答案 0 :(得分:360)
使用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
答案 1 :(得分:81)
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进程,而不是让shell启动子进程,而不会被杀死。 p.pid
将是您的cmd进程的ID。
p.kill()
应该有用。
我不知道这会对你的烟斗产生什么影响。
答案 2 :(得分:39)
如果您可以使用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)
答案 3 :(得分:20)
我可以用
来做from subprocess import Popen
process = Popen(command, shell=True)
Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))
它杀死了cmd.exe
和我给出命令的程序。
(在Windows上)
答案 4 :(得分:8)
当shell=True
shell是子进程时,命令是其子进程。所以任何SIGTERM
或SIGKILL
都会杀死shell而不是它的子进程,我不记得一个好方法。
我能想到的最好的方法是使用shell=False
,否则当你杀死父shell进程时,它会留下一个已经失效的shell进程。
答案 5 :(得分:6)
这些答案都不适合我,所以我离开了有效的代码。在我的情况下,即使用.kill()
终止进程并获得.poll()
返回代码,该进程也没有终止。
关注subprocess.Popen
documentation:
“...为了正确清理一个表现良好的应用程序应该杀死子进程并完成通信......”
proc = subprocess.Popen(...)
try:
outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()
就我而言,在调用proc.communicate()
后我错过了proc.kill()
。这会清除进程stdin,stdout ......并终止进程。
答案 6 :(得分:5)
正如Sai所说,shell是孩子,所以信号被它截获 - 我发现的最好的方法是使用shell = False并使用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()应该如你所愿。
答案 7 :(得分:1)
我觉得我们可以使用:
import os
import signal
import subprocess
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
os.killpg(os.getpgid(pro.pid), signal.SIGINT)
这不会杀死您的所有任务,而是杀死带有p.pid的进程
答案 8 :(得分:0)
我知道这是一个古老的问题,但这可能会对寻求其他方法的人有所帮助。这就是我在Windows上用来杀死已调用进程的方法。
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
subprocess.call(["taskkill", "/IM", "robocopy.exe", "/T", "/F"], startupinfo=si)
/ IM是图像名称,如果需要,您也可以执行/ PID。 / T杀死进程以及子进程。 / F强制终止它。如我所设置的,si是如何在不显示CMD窗口的情况下执行此操作。这段代码在python 3中使用。
答案 9 :(得分:0)
将信号发送到组中的所有进程
self.proc = Popen(commands,
stdout=PIPE,
stderr=STDOUT,
universal_newlines=True,
preexec_fn=os.setsid)
os.killpg(os.getpgid(self.proc.pid), signal.SIGHUP)
os.killpg(os.getpgid(self.proc.pid), signal.SIGTERM)
答案 10 :(得分:0)
我在这里没有看到此内容,因此我将其放在此处,以防有人需要。如果您要做的只是确保子流程成功终止,则可以将其放在上下文管理器中。例如,我希望我的标准打印机打印出一张图像,并使用上下文管理器确保子进程终止。
import subprocess
with open(filename,'rb') as f:
img=f.read()
with subprocess.Popen("/usr/bin/lpr", stdin=subprocess.PIPE) as lpr:
lpr.stdin.write(img)
print('Printed image...')
我相信这种方法也是跨平台的。
答案 11 :(得分:0)
Python 3.5
或+(实际上是在Python 3.8
上测试过)的一种非常简单的方法
import subprocess, signal, time
p = subprocess.Popen(['cmd'], shell=True)
time.sleep(5) #Wait 5 secs before killing
p.send_signal(signal.CTRL_C_EVENT)
然后,如果您具有键盘输入检测功能,则代码可能会在某些时候崩溃或类似的事情。在这种情况下,在给出错误的代码/函数行中,只需使用:
try:
FailingCode #here goes the code which is raising KeyboardInterrupt
except KeyboardInterrupt:
pass
此代码的作用只是向运行中的进程发送一个“ CTRL + C ”信号,这将导致该进程被杀死。
答案 12 :(得分:0)
这在 Pyhton 3.8.10 Win 10 上对我有用。
我试过 subprocess.Popen shell true:
但这确实https://stackoverflow.com/a/4789957/8518485
不要使用 os.kill()。
import subprocess
class ExecutableProgram:
program = None
def __init__(self,path):
self.path = path
def startProgram(self):
self.program = subprocess.Popen(self.path)
def stopProgram(self):
self.program.kill()
这就是你如何使用它:
from ExecutableProgram import ExecutableProgram
program = ExecutableProgram(r"<your executable>")
program.startProgram()
input()
program.stopProgram()
答案 13 :(得分:-1)
尽管这是一个老问题,但它在Google中的排名很高。因此,我决定发布一种答案,提出一种新方法,有人可以在python 3中使用它来轻松,自信地进行管理。从python 3.5开始,您已经在subprocess
包中添加了一个名为run()的新方法。
对于它可以处理的所有用例,建议使用此方法来调用子流程。对于更高级的用例,可以直接使用基础的
Popen
接口。
subprocess.run():
运行args描述的命令。等待命令完成,然后返回一个
CompletedProcess
实例。
例如,可以在python控制台中运行此代码段:
>>> subprocess.run(["ls", "-l"]) # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)
P.S。对于OP的特定问题,我无法重现他的问题。我使用popen()运行的命令正确终止。