我有一个简单的脚本,它将另一个python脚本作为子进程调用。我可以确认子进程已启动,我可以获取它的PID。
当我尝试终止子进程(在win中)时,我得到针对正确PID的SUCCESS消息,但Windows任务管理器显示第二个python.exe进程仍在运行。
在Win中完成此任务的任何建议?我将扩展它以最终在OSX和Linux中工作:
简化为:
#!/usr/bin/env python
import os, sys
import subprocess
from subprocess import Popen, PIPE, STDOUT, check_call
pyTivoPath="c:\pyTivo\pyTivo.py"
print "\nmyPID: %d" % os.getpid()
## Start pyTivo ##
py_process = subprocess.Popen(pyTivoPath, shell=True, stdout=PIPE, stderr=subprocess.STDOUT)
print "newPID: %s" % py_process.pid
## Terminate pyTivo ##
#py_process.terminate() - for nonWin (?)
py_kill = subprocess.Popen("TASKKILL /PID "+ str(py_process.pid) + " /f")
raw_input("\nPress Enter to continue...")
注意:需要Python2.7,psutils不可用
答案 0 :(得分:1)
使用/F
命令上的TASKKILL
(强制)开关。很多Windows命令没有有用的返回值。不要回想起TASKKILL
返回是否有用。
抱歉,忽略了您的/F
您可以尝试直接调用win32 api。
import win32api
win32api.TerminateProcess(int(process._handle), -1)
为此找到了ActiveState page。记录了许多kill方法,包括上面的Win32方法。
Windows不允许您终止进程的原因也很多。常见的原因是权限和错误的驱动程序,这些驱动程序具有待处理的I / O请求,这些请求无法正确响应kill信号。
有一些程序,例如ProcessHacker,它更热衷于杀死进程,但我不知道某些技术细节,虽然我怀疑强行关闭打开文件句柄等,然后调用终止参与。
你可以在Linux上遇到类似的问题,即没有杀死进程的权限,或者进程忽略了kill信号。但是在Linux上更容易解决,如果kill -9
不起作用,它就不会被杀死,这是一种罕见的情况,因为你必须在你的代码中明确地忽略信号9。
0)您可以使用TASKKILL /T
来杀死CMD和Python解释器。
1)如果您更改流程创建以直接创建python流程(而不是调用.py并依赖cmd启动),并使用脚本名称作为命令参数,您将获得创建流程时所期望的PID
2)您可以使用TASKKILL /IM
按名称终止进程,但名称将是python解释器,它可以杀死意外的进程。
答案 1 :(得分:1)
在我的实现中,以下实际上在Windows中创建了两个进程(“cmd.exe”和“python.exe”)。
py_process = subprocess.Popen(pyTivoPath, shell=True, stdout=PIPE, stderr=subprocess.STDOUT)
注意到“python.exe”进程是“cmd.exe”进程的子进程,我将“/ T”(树杀死)开关添加到我的TASKKILL:
py_kill = subprocess.Popen("TASKKILL /PID "+ str(py_process.pid) + " /f /t")
这样可以有效地杀死python子进程。
答案 2 :(得分:1)
创建了两个进程,因为您使用shell=True
调用Popen。看起来你需要使用shell的唯一原因是你使用与解释器的文件关联。要解决您的问题,您还可以尝试:
from subprocess Popen, PIPE, STDOUT
pyTivoPath = "c:\pyTivo\pyTivo.py"
cmd = r'c:\Python27\python.exe "{}"'.format(pyTivoPath)
# start process
py_process = Popen(cmd, stdout=PIPE, stderr=STDOUT)
# kill process
py_process.terminate()