如何在time.sleep()后终止subprocess子进程?
解决subprocess.Popen配合kill()/terminate()失效的问题
这个问题我太熟了!核心原因是你用了shell=True,导致subprocess.Popen创建的并不是VLC进程本身,而是一个中间的shell进程(比如Windows下的cmd.exe)。咱们一步步拆解问题和解决方案:
问题根源
当你设置shell=True时,Python会先启动一个shell进程,由这个shell去执行你指定的VLC命令。如果shell完成启动VLC的任务后就退出了,那你手里的pro对象对应的就是已经终止的shell进程——这时候调用pro.kill()当然没用,而且pro.pid是shell的PID,不是VLC的,所以用TASKKILL杀这个PID也关不掉VLC。
至于为什么直接连续调用kill()能生效?因为那时候shell进程还没来得及退出,杀掉shell会连带终止它的子进程(VLC);但插入time.sleep(4)后,shell已经完成启动任务并退出,pro指向的进程已经不存在了,自然无法生效。
解决方案
方案1:去掉shell=True(最推荐)
你的命令里已经明确指定了VLC的完整路径,完全不需要shell来解析,直接去掉shell=True即可:
import subprocess import time # 用原始字符串避免路径转义问题 pro = subprocess.Popen([r"C:\Program Files\VideoLAN\VLC\VLC.exe", r'e:\Download\PUA elit.xspf']) time.sleep(4) pro.kill()
这时pro直接指向VLC进程,pro.pid就是任务管理器里显示的VLC PID,kill()也能正常终止VLC。
方案2:必须用shell=True时,跟踪子进程
如果因为某些特殊需求必须保留shell=True,可以用psutil库来跟踪shell进程的子进程(也就是VLC),然后杀掉它:
- 先安装psutil:
pip install psutil
- 代码示例:
import subprocess import time import psutil pro = subprocess.Popen([r"C:\Program Files\VideoLAN\VLC\VLC.exe", r'e:\Download\PUA elit.xspf'], shell=True) time.sleep(4) try: # 获取shell进程对象 parent_process = psutil.Process(pro.pid) # 递归获取所有子进程(包括VLC) child_processes = parent_process.children(recursive=True) # 杀掉所有子进程 for child in child_processes: child.kill() # 最后杀掉shell进程本身 pro.kill() except psutil.NoSuchProcess: # 如果shell进程已经提前退出,直接跳过即可 pass
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

