无法在 Windows 上使用 Python 终止正在运行的子进程

Posted

技术标签:

【中文标题】无法在 Windows 上使用 Python 终止正在运行的子进程【英文标题】:Can't kill a running subprocess using Python on Windows 【发布时间】:2015-10-18 08:26:45 【问题描述】:

我有一个 Python 脚本,它每 60 秒运行一整天检查时间,因此它可以在一天中的特定时段启动/结束任务(其他 Python 脚本)。

这个脚本运行几乎一切正常。任务在正确的时间开始并通过新的cmd 窗口打开,因此主脚本可以继续运行并采样时间。唯一的问题是它不会杀死任务。

import os
import time
import signal
import subprocess
import ctypes


freq = 60 # sampling frequency in seconds

while True:    
    print 'Sampling time...'
    now = int(time.time())

    #initialize the task.. lets say 8:30am
    if ( time.strftime("%H:%M", time.localtime(now)) == '08:30'):
        # The following method is used so python opens another cmd window and keeps original script running and sampling time 
        pro = subprocess.Popen(["start", "cmd", "/k", "python python-task.py"], shell=True)

    # kill process attempts.. lets say 11:40am
    if ( time.strftime("%H:%M", time.localtime(now)) == '11:40'):
        pro.kill()    #not working - nothing happens

        pro.terminate()    #not working - nothing happens

        os.kill(pro.pid, signal.SIGINT) #not working - windows error 5 access denied

        # Kill the process using ctypes - not working - nothing happens
        ctypes.windll.kernel32.TerminateProcess(int(pro._handle), -1)

        # Kill process using windows taskkill - nothing happens
        os.popen('TASKKILL /PID '+str(pro.pid)+' /F')

    time.sleep(freq)

重要提示:任务脚本python-task.py 将无限期运行。这就是为什么我需要能够在它仍在运行的特定时间“强制”杀死它。

有什么线索吗?我究竟做错了什么?怎么杀?

【问题讨论】:

您是否以管理员身份运行主脚本。如果不是,那可能会导致杀死 python-task.py 进程。后者也可以配置为检查某个文件是否存在,如果该文件存在则退出。然后主脚本可以创建该文件以导致 python-task.py 进程停止。所有 python-task.py 进程都可能有一个这样的文件,或者每个进程都有一个唯一的文件,在这种情况下,它的名称可以作为参数传递,并且主脚本必须跟踪这些名称。 @TrisNefzger 我已经阅读了有关文件解决方案的信息,但是如果我可以仅处理 kill-process 而不是编辑 python-task.py 文件来解决这个问题,那就更好了。如何授予我以管理员身份运行主脚本?我应该使用什么杀死方法? afaik windows 没有这个能力...打开任务管理器...选择任务并从那里杀死它... 哦,我可能撒谎了code.activestate.com/recipes/… 你为什么要重写windows scheduler? 【参考方案1】:

您正在杀死生成子进程的外壳,而不是您的子进程。

编辑:来自文档:

您需要在 Windows 上指定 shell=True 的唯一情况是您希望执行的命令内置于 shell 中(例如 dir 或 copy)。您不需要 shell=True 来运行批处理文件或基于控制台的可执行文件。

警告

如果与不受信任的输入结合使用,则传递 shell=True 可能会带来安全隐患。有关详细信息,请参阅常用参数下的警告。

因此,不要传递单个字符串,而是分别传递列表中的每个参数,并避免使用 shell。您可能希望对子级和父级使用相同的可执行文件,因此通常是这样的:

pro = subprocess.Popen([sys.executable, "python-task.py"])

【讨论】:

以上是关于无法在 Windows 上使用 Python 终止正在运行的子进程的主要内容,如果未能解决你的问题,请参考以下文章

过程入口点终止无法位于动态链接库中

来自 ant 的 PsExec 不会终止

Windows 上的 Python 2.6:如何使用“shell=True”参数终止 subprocess.Popen?

如何防止WINDOWS服务被终止或被禁用?

在管道块上读取,直到在管道末端运行的程序终止 - Windows

无法识别使用 Ubuntu bash 在 Windows 10 上安装的 Python 模块