【问题标题】:Kill the Popen child process杀死 Popen 子进程
【发布时间】:2014-03-28 02:51:23
【问题描述】:

这是我第一次在社区发帖,但我通过搜索大约 2 周的时间一直在学习我能做的事情。我似乎陷入了死胡同,我似乎无法通过反复试验或阅读其他帖子找到答案。

此时我要做的就是终止由 Popen 和 shell 本身创建的进程。我必须补充一点,我是编程新手,这是我的第一个“真实”世界任务。

我见过的解决方案是创建一个组 ID,但这是针对 Unix 而我在 Windows 上的。 Popen.kill() 和 Popen.terminate() 不会杀死 shell 的孩子。这段代码启动的程序不会退出,它的PID与shell的PID不同。我愿意接受建议,因为我将其用作学习工具和富有成效的东西。其他一些解决方案不会终止该过程。我可以通过 DOS 和 Python 解释器杀死它,但是我必须手动从 TASKLIST 中查找 PID,然后输入它。我需要从这个程序中杀死它。

我正在构建此代码以保存 MathCad 模板的多个文档,该模板读取 excel 文档的值,并使用新文件名输出保存的文档。提前致谢。请原谅您可能看到的任何新手编码内容,因为我只是想弄湿我的脚。

已尝试和更新的其他任务(2014 年 2 月 26 日):

尝试使用 subprocess.call('TASKKILL ...) 而不是 subprocess.Popen 杀死程序。它不会杀死由 shell 创建的孩子。尝试用 subprocess.call('....', shell=True) 替换 proc = subprocess.Popen(' ....' shell=True ) 并且 SendKeys 函数不再起作用。尝试了带有 kill_proc_tree 函数的 psutil 函数和“EOFError:[WinError 10054] 现有连接被远程主机强制关闭”弹出窗口。子程序仍然没有关闭。

如果我删除 kill/terminate/close 命令并让程序运行,则 proc.pid 与 os.getpid() 不同。如果我使用 psutil.Process(proc.pid) - 它表示当 Python 解释器将返回其 PID 时该进程不存在。如果我得到 MathCadPrime.exe PID = 例如来自 TASKLIST 的 1111 并使用 psutil.Process(1111).parent,它显示没有父母。这可能是为什么在 shell 上执行 TASKKILL 不会关闭孩子的原因?我已经完全按照我写的代码发布了我的代码,看看你们是否能看到我没有看到的东西。

#def kill_proc_tree(pid, including_parent=True):
#    parent = psutil.Process(pid)
#    for child in parent.get_children(recursive=True):
#        child.kill()
#    if including_parent:
#        parent.kill()

import subprocess
import win32api
import win32com.client
import time
import os
import signal
import psutil

# User files
file = "C:\Directory\SubDirectory\file.mcdx"


# Command line function
# /B /D - No command line window or explorer window    
proc = subprocess.Popen('start /B /D                                            \
        "C:\Program Files\PTC\Mathcad\Mathcad Prime 2.0\" "MathcadPrime.exe"    \
        "C:\Directory\SubDirectory\file.mcdx"', shell=True)

# Set and test for active window
    focus = False
    while (focus == False):
            focus = shell.AppActivate("MathCad Prime 2.0 - " + file)
            time.sleep(1)
            if (focus == True):
                break

# Send MathCad Prime commands
shell.SendKeys('%', 0)
time.sleep(0.5)
shell.SendKeys('c', 0)
time.sleep(0.1)
shell.SendKeys('c', 0)
time.sleep(2.0)
shell.SendKeys('%', 0)
time.sleep(0.5)
shell.SendKeys('f', 0)
time.sleep(0.1)
shell.SendKeys('s', 0)
time.sleep(4.0)



#Other methods to tried to kill children:

#Method 1:
#subprocess.call("TASKKILL /F /T /PID {pid}".format(pid=proc.pid))

#Method 2:
#subprocess.Popen("TASKKILL /F /T /PID {pid}".format(pid=proc.pid))

#Method 3:
#if (int(proc.pid) > 0):
#    os.kill(proc.pid, signal.SIGTERM)

#Method 4 (used with kill_proc_tree):
#proc1 = os.getpid()
#kill_proc_tree(proc1)

【问题讨论】:

  • 你有read the docs吗?
  • 是的。 Popen.kill() 和 Popen.terminate() 不会杀死 shell 的孩子。这段代码启动的程序并没有退出,它的PID和shell的PID不同。
  • 好的,谢谢你的澄清
  • 你想杀死整个进程树:shell、它的子进程等等?您当前的代码有什么问题?
  • 尝试将 /t 添加到 taskkill,这应该也会杀死被杀死进程的所有子进程。

标签: python windows popen


【解决方案1】:

感谢大家的帮助,你们帮我得出了结论。与建议的略有不同,但每次都能完成工作。我在家里,而不是在工作(所以我把这个写在我的脑海里),但基本上我所做的只是将 TASKLIST 写入一个文本文件并过滤掉一串代码:

os.chdir('C:\Code')
subprocess.call('TASKLIST /fi "IMAGENAME eq MathcadPrime.exe" /nh /fo csv > task.txt)

然后解析出PID:

doc = open('task.txt', 'rt')
parse = doc.read()
listing = parse.split(",")
PID = listing[1]
PID = int(PID.replace('"','').replace("'",""))
os.kill(PID, signal.SIGTERM)

我希望这对其他人有帮助。

【讨论】:

  • 注意:它会杀死一个名为 "MathcadPrime.exe" 的进程(在 Unix 上类似于 pkill processname)。这是与杀死进程树不同的问题。如果MathcadPrime.exe 被杀死时也会留下子进程,你会怎么做?
  • @J.F.Sebastian 好问题 J.F.,我不知道。我不相信 Mathcad 会以我使用它的方式产生任何其他进程。这是一个简单的打开,执行几个过程,然后保存/关闭。我绝对愿意接受使代码更紧凑的解决方案。我会尝试杀死整个进程树,但我不知道如何解决我之前发布的问题。
  • psutil-based solution 应该可以工作。
  • 任务列表并非在所有版本的 windows 上都可用。
【解决方案2】:

我尝试了以下代码,它对我有用:

import subprocess
import os,signal
proc = subprocess.Popen('dir /S', shell=True)
if (int(proc.pid) > 0):
    print "killing ",proc.pid
    print os.kill(proc.pid, signal.SIGTERM)

我还观察到,如果从 Popen 启动的程序响应“Ctrl+C”,您可以使用 signal.CTRL_C_EVENT 关闭程序。如果启动的程序没有响应事件,则必须手动关闭它。我认为,我上面的代码有效,因为 cmd.exe 响应了事件。

【讨论】:

  • 我收到“[WinError5] 访问被拒绝”错误。不知道是我公司的管理权限还是别的什么。我将不得不做更多的研究并与您联系,我会在家里试一试以确定管理员权限。
  • 你也可以试试 SIGKILL。您可以通过尝试在 python 之外终止进程来确定您的用户帐户是否具有特权。
猜你喜欢
  • 2011-06-11
  • 1970-01-01
  • 1970-01-01
  • 2010-12-08
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多