无法在 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 终止正在运行的子进程的主要内容,如果未能解决你的问题,请参考以下文章
Windows 上的 Python 2.6:如何使用“shell=True”参数终止 subprocess.Popen?