如何在关闭命令窗口脚本后终止后台运行的program.exe进程
嘿,我看你遇到的问题是用Python脚本启动了program.exe之后,关闭命令窗口,这个后台进程还在偷偷跑对吧?我来给你几个实用的解决办法,直接改改你的代码就能搞定。
先给你分析下当前代码的问题:你用subprocess.Popen启动了子进程,然后调用process.communicate()——这个方法会一直卡住,直到子进程跑完才会执行后面的print(command)。但如果是直接关掉命令窗口(不是等脚本正常执行完),Python父进程被强制终止,子进程就会变成“孤儿进程”,脱离控制继续在后台运行。
方案1:添加退出钩子+信号处理,主动终止子进程
这个方法的思路是:给Python脚本注册一个“退出时要做的事”,不管是正常退出还是遇到强制终止信号(比如Ctrl+C、关闭窗口),都先杀掉program.exe再退出。
修改后的代码如下:
import subprocess import atexit import signal import sys def kill_child_process(proc): # 先检查进程是否还在运行 if proc.poll() is None: proc.terminate() # 发送终止信号 proc.wait() # 等待进程彻底结束,避免残留 command = [ "program.exe", "-i", "-o", ] # 启动子进程 process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=1, universal_newlines=True, ) # 注册退出钩子:脚本正常结束时自动执行kill操作 atexit.register(kill_child_process, process) # 处理Windows下的终止信号(比如Ctrl+C、关闭控制台窗口) def handle_termination(signal_num, frame): kill_child_process(process) sys.exit(0) # 针对Windows系统注册信号处理器 if sys.platform == "win32": # 处理Ctrl+C和Ctrl+Break signal.signal(signal.SIGINT, handle_termination) signal.signal(signal.SIGBREAK, handle_termination) try: # 等待子进程完成并获取输出 stdout, stderr = process.communicate() print(command) except KeyboardInterrupt: # 捕获手动中断,确保子进程被终止 kill_child_process(process) sys.exit(0)
方案2:让子进程和父进程绑定(Windows专属)
在Windows下,我们可以通过设置进程创建标记,让program.exe和Python脚本共享进程组,这样关闭命令窗口时,子进程会跟着父进程一起被终止。
只需要修改subprocess.Popen的参数,添加creationflags:
process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, bufsize=1, universal_newlines=True, # 让子进程加入父进程的进程组 creationflags=subprocess.CREATE_NEW_PROCESS_GROUP )
这个方法更简单,但要注意:如果你的program.exe本身会再启动其他子进程,可能需要额外处理;另外,这种方式依赖Windows的进程组机制,兼容性很好,但如果是在Linux/macOS下,就得用start_new_session参数来实现类似效果。
小提醒:如果不需要捕获program.exe的输出,你可以去掉stdout=subprocess.PIPE和stderr=subprocess.PIPE,让它直接关联到控制台窗口,这样关闭窗口时系统会自动终止它,代码会更简单~
备注:内容来源于stack exchange,提问作者Oussama Gamer




