Is there a way to make os.killpg not kill the script that calls it?

use*_*833 1 python subprocess

I have a subprocess which I open, which calls other processes.

I use os.killpg(os.getpgid(subOut.pid), signal.SIGTERM) to kill the entire group, but this kills the python script as well. Even when I call a python script with os.killpg from a second python script, this kills the second script as well. Is there a way to make os.killpg not stop the script?

Another solution would be to individually kill every child 1process. However, even using

p = psutil.Process(subOut.pid)
child_pid = p.children(recursive=True)
for pid in child_pid:
    os.kill(pid.pid, signal.SIGTERM)
Run Code Online (Sandbox Code Playgroud)

does not correctly give me all the pids of the children.

And you know what they say... don't kill the script that calls you...

atl*_*eta 5

回答有点晚,但由于谷歌在寻找相关问题时将我带到这里:您的脚本被杀死的原因是因为它的子项默认情况下会继承其组 ID。但是您可以告诉subprocess.Popen为您的子流程创建一个新的流程组。虽然这是一个小技巧:你必须传递os.setpgrppreexec_fn参数。这将在新创建的(分叉的)进程(在执行 exec 之前)中调用 setpgrp(不带任何参数),它将gid新进程的pid设置为新进程的(从而创建一个新组)。该文档提到它可以在多线程代码中死锁。作为替代方案,您可以使用start_new_session=True,但这不仅会创建一个新的进程组,还会创建一个新的会话。(这意味着如果你在脚本运行时关闭终端会话,子进程不会被终止。这可能是也可能不是问题。)

作为一个侧面说明,如果你是在Windows上,你可以简单地通过subprocess.CREATE_NEW_PROCESS_GROUPcreationflag参数。

这是它的详细信息:

subOut = subprocess.Popen(['your', 'subprocess', ...], preexec_fn=os.setpgrp)

# when it's time to kill
os.killpg(os.getpgid(subOut.pid), signal.SIGTERM)
Run Code Online (Sandbox Code Playgroud)


Viv*_*wal 0

创建一个进程组,其中包含被调用进程的所有直接子进程,如下所示:

p1 = subprocess.Popen(cmd1)
os.setpgrp(p1.pid, 0) #It will create process group with id same as p1.pid
p2 = subprocess.Popen(cmd2)
os.setpgrp(p2.pid, os.getpgid(p1.pid))

pn = subprocess.Popen(cmdn)
os.setpgrp(pn.pid, os.getpgid(p1.pid))

#Kill all the children and their process tree using following command
os.killpg(os.getpgid(p1.pid), signal.SIGKILL)
Run Code Online (Sandbox Code Playgroud)

它将杀死除自己的进程之外的整个进程树。