我用下面的命令启动一个子进程:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
然而,当我试图杀死使用:
p.terminate()
or
p.kill()
该命令一直在后台运行,因此我想知道如何实际终止该进程。
注意,当我使用以下命令运行时:
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
它在发出p.terminate()时成功终止。
完整的解决方案,将通过回调函数在达到超时或特定条件时终止运行进程(包括子树)。
在windows和Linux上都可以使用,从Python 2.7到本文撰写时的3.10。
使用pip Install command_runner安装
超时示例:
from command_runner import command_runner
# Kills ping after 2 seconds
exit_code, output = command_runner('ping 127.0.0.1', shell=True, timeout=2)
具体情况示例:
在这里,如果当前系统时间秒数为> 5,我们将停止ping
from time import time
from command_runner import command_runner
def my_condition():
# Arbitrary condition for demo
return True if int(str(int(time()))[-1]) > 5
# Calls my_condition() every second (check_interval) and kills ping if my_condition() returns True
exit_code, output = command_runner('ping 127.0.0.1', shell=True, stop_on=my_condition, check_interval=1)
正如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()应该按您期望的方式工作。
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()应该工作。
我不知道这会对你的烟斗有什么影响。
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”信号,这将导致进程被杀死。