Python脚本关闭时用atexit和subprocess终止子进程失败的问题
问题解决:Python退出时终止后台运行的run.exe
你的代码核心问题是clear函数里传的process是Popen对象,不是进程名称或PID,导致TASKKILL命令执行无效。下面是修复后的可行方案:
修复后的完整代码
import subprocess import sys import atexit import signal # 终止指定进程 def clear(process): try: # 先尝试优雅终止,超时则强制杀死 process.terminate() process.wait(timeout=3) except subprocess.TimeoutExpired: process.kill() except Exception: # 进程可能已自行退出,忽略错误 pass # 处理Windows下的中断信号(如Ctrl+C) def handle_signal(signum, frame): sys.exit(0) def run(): exe_path = "engine/run.exe" startupinfo = None if sys.platform == "win32": startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW # 注册信号处理,确保异常退出时也能触发清理逻辑 signal.signal(signal.SIGINT, handle_signal) signal.signal(signal.SIGBREAK, handle_signal) process = subprocess.Popen( exe_path, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, startupinfo=startupinfo, creationflags=subprocess.CREATE_NO_WINDOW, # 移除CREATE_NEW_PROCESS_GROUP,避免子进程脱离控制 close_fds=True, shell=False, ) atexit.register(clear, process)
关键修改说明
- 移除
CREATE_NEW_PROCESS_GROUP:该标志会让子进程创建独立进程组,导致terminate()无法直接终止它,去掉后可直接通过Popen对象控制子进程。 - 替换进程终止方式:用Popen对象自带的
terminate()和kill()替代外部TASKKILL命令,避免参数错误,逻辑更可靠。 - 添加信号处理:在Windows下,Ctrl+C、任务管理器关闭进程等场景会触发特定信号,注册处理函数确保
atexit的清理逻辑能被执行。 - 异常容错:避免进程已自行退出时抛出错误,不影响脚本正常退出。
验证方式
如果仍有疑问,可以在clear函数中添加打印语句,确认清理逻辑是否被执行:
def clear(process): print(f"正在终止进程PID: {process.pid}") # 后续终止逻辑...
内容的提问来源于stack exchange,提问作者Smoodie
相关产品推荐
相关产品推荐

