Python父进程终止后无法终止已启动子进程的问题求助
Python父进程终止后无法终止已启动子进程的问题求助
我来帮你搞定这个问题!首先咱们得先弄明白为啥会出现这种情况:你现在的master脚本启动完三个子进程之后就直接退出了(或者你按Ctrl+C的时候,master已经把所有子进程都启动好了),这些子进程会变成孤儿进程,被系统的init(或者systemd)进程接管,所以会继续跑下去。而且你原来的try-except只包裹了启动子进程的代码,根本覆盖不到master启动完成后的中断信号处理。
下面给你两个实用的解决方案,你可以根据需求选:
方案一:保存子进程实例,主动终止
这个方法最直观,让master脚本保持运行,捕获中断信号后逐个终止所有子进程。修改后的master脚本如下:
import sys, subprocess, os, signal from time import sleep d = ['fool', 'gool', 'lool'] children = [] # 用来保存所有子进程实例 try: # 启动所有子进程并记录 for i in range(3): proc = subprocess.Popen( ['python3', 'child.py', d[i], str(i + 3)], stdin=subprocess.PIPE ) children.append(proc) # 让master保持运行状态,直到收到中断信号 while True: sleep(1) except KeyboardInterrupt: print("收到终止信号,正在关闭所有子进程...") # 遍历所有子进程,发送终止信号 for proc in children: proc.terminate() # 如果terminate不够用,可以换成proc.kill()强制杀死 sys.exit(0)
这样当你按Ctrl+C时,master会捕获到KeyboardInterrupt,然后逐个通知子进程终止,完美解决问题。
方案二:使用进程组批量终止
如果子进程数量很多,逐个终止太麻烦,可以用进程组的方式,一次性把所有子进程都干掉。这个方法在Linux/macOS下效果很好,修改后的master脚本:
import sys, subprocess, os, signal from time import sleep d = ['fool', 'gool', 'lool'] children = [] # 定义信号处理函数,收到中断时终止整个进程组 def handle_interrupt(sig, frame): print("正在终止所有子进程...") # 向当前进程组发送终止信号 os.killpg(os.getpgid(0), signal.SIGTERM) sys.exit(0) # 注册SIGINT信号(也就是Ctrl+C触发的信号)的处理函数 signal.signal(signal.SIGINT, handle_interrupt) try: for i in range(3): proc = subprocess.Popen( ['python3', 'child.py', d[i], str(i + 3)], stdin=subprocess.PIPE, preexec_fn=os.setsid # 让子进程加入新的会话/进程组 ) children.append(proc) # 保持master运行 while True: sleep(1) except Exception as e: print(f"启动子进程时出错:{str(e)}") for proc in children: proc.terminate() sys.exit(1)
这里用preexec_fn=os.setsid让每个子进程都加入同一个进程组,当master收到Ctrl+C时,直接向整个进程组发送终止信号,所有子进程都会收到并停止运行。
另外提个小细节:你的child脚本里每次循环都用open(f"{arg}.txt", "w"),这会每次覆盖文件内容,如果你想追加内容的话,可以改成open(f"{arg}.txt", "a")哦~
备注:内容来源于stack exchange,提问作者NedStarkOfWinterfell
相关产品推荐
相关产品推荐

