Python:终止subprocess = Success,但它仍在运行(?)

时间:2015-06-16 11:53:47

标签: python python-2.7

我有一个简单的脚本,它将另一个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不可用

3 个答案:

答案 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()