简体   繁体   English

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

[英]Python: Terminate subprocess = Success, but it's still running (?)

I have a simple script that calls another python script as a subprocess. 我有一个简单的脚本调用另一个python脚本作为子进程。 I can confirm the subprocess is started and I can grab its PID. 我可以确认子进程已启动,我可以获取其PID。

When I attempt to terminate the subprocess (in win), I get the SUCCESS message against the correct PID, but Windows task manager shows the 2nd python.exe process to still be running. 当我尝试终止子进程(在win中)时,我得到针对正确PID的SUCCESS消息,但Windows任务管理器显示第二个python.exe进程仍在运行。

Any suggestions to accomplish this task in Win? 在Win中完成此任务的任何建议? I'll be extending this to also work in OSX and Linux eventually: 我将扩展它以最终在OSX和Linux中工作:

Simplified: 简化:

#!/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...")

Note: Python2.7 required, psutils not available 注意:需要Python2.7,psutils不可用

Use the /F (Force) switch on the TASKKILL command. 使用TASKKILL命令上的/F (强制)开关。 Lots of windows commands do not has useful return values. 很多Windows命令没有有用的返回值。 Don't recall if TASKKILL returns has a useful value. 不记得TASKKILL返回是否具有有用的值。


Sorry, overlooked your /F 对不起,忽略了你的/F

You could try calling the win32 api directly. 您可以尝试直接调用win32 api。

import win32api
win32api.TerminateProcess(int(process._handle), -1)

Found the ActiveState page for this. 找到了ActiveState页面 Documents a number of kill methods, including the Win32 approach above. 记录了一些kill方法,包括上面的Win32方法。

There are also a number of reasons why Windows will not allow you to terminate a process. Windows不允许您终止进程的原因也有很多。 Common reasons are permissions and buggy drivers that have pending I/O requests that don't response to the kill signal properly. 常见原因是权限和错误驱动程序具有未正确响应kill信号的挂起I / O请求。

There are some programs, eg ProcessHacker, that are more enthusiastic about killing processes, but I don't know the technical details for certain, though I suspect forced closing of open file handles etc. and then calling Terminate are involved. 有一些程序,例如ProcessHacker,对杀死进程更加热衷,但我不知道技术细节,虽然我怀疑强制关闭打开文件句柄等,然后调用Terminate。

You can have similar issues on Linux, ie, no permission to kill process or the process is ignoring the kill signal. 你可以在Linux上遇到类似的问题,即没有杀死进程的权限,或者进程忽略了kill信号。 Easier to resolve on Linux though, if kill -9 does not work, it can't be killed and it is a rarer condition because you have to ignore signal 9 explicitly in your code. 但是在Linux上更容易解决,如果kill -9不起作用,它就不能被杀死,这是一种罕见的情况,因为你必须在你的代码中明确地忽略信号9。


0) You could use TASKKILL /T to kill CMD and the Python interpreter. 0)您可以使用TASKKILL /T来杀死CMD和Python解释器。

1) If you change your process creation to create the python process directly (instead of invoking the .py and relying on cmd to launch) with the script name as command argument you will get the PID you expect when you create the process. 1)如果您更改流程创建以直接创建python流程(而不是调用.py并依赖cmd启动),并使用脚本名称作为命令参数,您将获得创建流程时所期望的PID。

2) You could use TASKKILL /IM to kill the process by name, but the name will be the python interpreter and it could kill unintended processes. 2)您可以使用TASKKILL /IM按名称TASKKILL /IM进程,但名称将是python解释器,它可能会杀死意外的进程。

In my implementation, the following actually creates TWO processes in Windows ("cmd.exe" and "python.exe"). 在我的实现中,以下实际上在Windows中创建了两个进程(“cmd.exe”和“python.exe”)。

py_process = subprocess.Popen(pyTivoPath, shell=True, stdout=PIPE, stderr=subprocess.STDOUT)

Noticing the "python.exe" process is a child of the "cmd.exe" process, I added the "/T" (tree kill) switch to my TASKKILL: 注意到“python.exe”进程是“cmd.exe”进程的子进程,我将“/ T”(树杀死)开关添加到我的TASKKILL:

py_kill = subprocess.Popen("TASKKILL /PID "+ str(py_process.pid) + " /f /t") 

This results in the desired effect to effectively KILL the python subprocess. 这导致有效杀死python子进程的期望效果。

Two processes are created because you call Popen with shell=True . 创建了两个进程,因为您使用shell=True调用Popen。 It looks like the only reason you need to use a shell is so you make use of the file association with the interpreter. 看起来你需要使用shell的唯一原因是你使用与解释器的文件关联。 To resolve your issue you could also try: 要解决您的问题,您还可以尝试:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM