【问题标题】:How to know if an external process has finished in python?如何知道外部进程是否已在 python 中完成?
【发布时间】:2015-01-05 08:32:24
【问题描述】:

我在 Windows 平台上工作。在我的 python 脚本中,我可以通过以下方式调用外部程序:

os.system("C:\mainfolder\menu.exe C:\others\file1.inp C:\others\file2.inp")

os.popen("C:\mainfolder\menu.exe C:\others\file1.inp C:\others\file2.inp")

subprocess.call(["C:\mainfolder\menu.exe","C:\others\file1.inp" "C:\others\file2.inp"])

地点:

menu.exe:是我的外部程序。

file1 和 file2:是我的外部程序的输入文件。

以上所有工作正常。现在我的外部程序已经成功完成,我需要完全关闭它以及它打开的所有窗口。我浏览了许多其他帖子、python 文档等,并找到了一些命令,例如:

os.system("taskkill /im C:\mainfolder\menu.exe")

os.kill(proc.pid,9)

child.kill() 

但他们没有工作。我花了很多时间试图找到对我有用的东西,直到我意识到无论我输入哪个命令,它们都不会被读取,因为计算机不知道我的外部程序已经完成。这就是为什么我可以随时通过键入 taskkill /im menu.exe 从命令行轻松终止程序,而不是从 python。

有人知道如何解决这个问题吗?当我调用外部程序时,我是否应该包含其他内容?

【问题讨论】:

  • 如果您调用的程序打开了其他程序,您可能对此无能为力。不过我不确定。
  • 说真的?,我对编程了解不多,但我一直认为在编程中一切皆有可能。希望我能找到答案:-(
  • 如果您可以修改打开的程序以在它们关闭之前/关闭时向您的进程发送信号(例如通过 DBus),您可以使用 IPC 来解决这个问题。
  • 你不能对它做任何事情并不是真的,只是答案可能对于windows来说被深深地隐藏了。在 linux 中,使用 -9 开关 kill 将终止所述进程及其子/父进程,我不确定 taskkill 的哪个开关与此等效。
  • 实际上,您是否尝试将 /F 添加到您的 taskkill 中?

标签: python windows terminate external-process


【解决方案1】:

这里有一些示例代码,如何检测程序是否打开了一个窗口。您只需要知道消息框的标题,menu.exe 在完成后打开:

import subprocess
import win32gui
import time


def enumHandler(hwnd, lParam):
    if win32gui.IsWindowVisible(hwnd):
        if 'Menu.exe Finished' in win32gui.GetWindowText(hwnd):
            proc.kill()

proc = subprocess.Popen(["C:\mainfolder\menu.exe","C:\others\file1.inp" "C:\others\file2.inp"])
while proc.poll() is None:
    win32gui.EnumWindows(enumHandler, None)
    time.sleep(1)

【讨论】:

  • 这段代码在检测到有活动窗口时会终止我的程序吗?
  • 终止程序,如果有一个具有特定标题的窗口。
  • 这是一个非常有用的代码,我不知道。但是,在我的情况下,该窗口在过程的一开始就打开。当我的程序运行时,它会说:处理中,当它完成处理我的数据时,它会说:完成。窗口的标题保持不变。窗口的标题是我的程序的名称。可能有一种方法可以从窗口中提取完成的单词而不是标题?。
  • @Sarah:所以这更复杂。您必须找到窗口,查看它的所有子元素以查找带有文本finished 的标签。这是 stackoverflow 的答案:stackoverflow.com/questions/14500026/…
  • 谢谢丹尼尔,我仍在阅读您提供的链接。关于您上面的代码,这是否意味着如果我使用以下方法调用我的程序: proc = subprocess.Popen(["C:\mainfolder\menu.exe","C:\others\file1.inp" "C:\others \file2.inp"]),它会读取下面的代码吗?
【解决方案2】:

如果你想让一个进程立即结束,即等待它结束,这是一个阻塞调用,os.system() 通常会等待,讨论了here 以及.communicate[0] 使用子进程there

如果你想在程序的后面结束一个进程,一个异步的、非阻塞的进程,也许得到它的pid,这取决于shell=True是否是spawned shell的pid或的子进程。

该 pid 可用于通过使用 psutil 或 os 来结束它immediately,或者使用很少的 cpu 时间来结束它wait until it ends,但可以在等待时完成其他任务,或者可以使用线程。

【讨论】:

    【解决方案3】:

    在几个月前我问过这个问题时,将我的发现发布到这个问题可能有点晚,但它可能对其他读者仍然有帮助。

    在尝试回答我的问题的人的帮助下,尤其是 Daniel 的回答,我找到了解决问题的方法。不确定它是否是最好的,但我得到了我需要的东西。

    基本上,我没有在弹出窗口中寻找“完成”一词,而是寻找外部程序生成的结果。如果这些结果都产生了,就说明程序已经结束了,那么我就kill掉这个进程:

     proc=subprocess.Popen(["C:\mainfolder\menu.exe","C:\others\file1.inp" "C:\others\file2.inp"])
     while proc.poll() is None:
         if os.path.exists("D:\\Results_folder\\Solution.txt"):
               time.sleep(10)
               os.system('taskkill /im menu.exe')
    

    【讨论】:

    • 您可以使用Popen.pid 来获取您生成的子进程的进程ID。然后你可以在循环中调用kill -0 PID(如果你使用的是Windows,检查kill在那里的行为!)直到它的返回值变为0或None
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-06
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多