python杀死父进程但子进程离开了

时间:2015-12-01 12:14:46

标签: python subprocess

当我尝试杀死python进程时,通过{ "query": { "query": { "query_string": { "query": "*john*", "default_field": "name" } }, "filtered": { "filter": { "bool": { "must": [ { "term": { "age": 21 } }, { "term": { "location": "New York" } } ] } } } }, "aggs": { "group_by_name": { "terms": { "field": "name" } } } } 启动的子进程不会同时终止。

Killing child process when parent crashes in pythonPython Process won't call atexit (atexit看起来不适用于信号)

这是否意味着我需要自己处理这种情况?如果是这样,那么首选方法是什么?

os.system

示例代码:

main.py

> python main.py
> ps
4792 ttys002    0:00.03 python run.py
4793 ttys002    0:00.03 python loop.py 
> kill -15 4792
> ps 
4793 ttys002    0:00.03 python loop.py

loop.py

import os
os.system('python loop.py')

UPDATE1

我做了一些实验,发现了一个可行的版本,但仍然对这个逻辑感到困惑。

import time

while True:
    time.sleep(1000)

1 个答案:

答案 0 :(得分:2)

kill -15 4792在您的示例中向SIGTERM发送run.py - 它不会向loop.py(或其父shell)发送任何内容。默认情况下,SIGTERM不会传播到进程树中的其他进程。

os.system('python loop.py')至少开始两次处理shell和python进程。你不需要它;使用subprocess.check_call()来运行没有隐式shell的单个子进程。顺便说一句,如果你的subprocess is a Python script; consider importing it and running corresponding functions instead

os.killpg(0, SIGKILL)向当前进程组发送SIGKILL信号。 shell为每个管道创建一个新的进程组(作业),因此父级中的os.killpg()对子级没有影响(请参阅更新)。请参阅How to terminate a python subprocess launched with shell=True

#!/usr/bin/env python
import subprocess
import sys

try:
    p = subprocess.Popen([executable, 'loop'])
except EnvironmentError as e: # 
    sys.exit('failed to start %r, reason: %s' % (executable, e))
else:
    try: # wait for the child process to finish
        p.wait()
    except KeyboardInterrupt: # on Ctrl+C (SIGINT)
        #NOTE: the shell sends SIGINT (on CtrL+C) to the executable itself if
        #  the child process is in the same foreground process group as its parent 
        sys.exit("interrupted")

更新

似乎os.system(cmd)没有为cmd创建新的流程组:

>>> import os
>>> os.getpgrp()
16180
>>> import sys
>>> cmd = sys.executable + ' -c "import os; print(os.getpgrp())"'
>>> os.system(cmd) #!!! same process group
16180
0
>>> import subprocess
>>> import shlex
>>> subprocess.check_call(shlex.split(cmd))
16180
0
>>> subprocess.check_call(cmd, shell=True)
16180
0
>>> subprocess.check_call(cmd, shell=True, preexec_fn=os.setpgrp) #!!! new
18644
0

因此,您的示例中的os.system(cmd)应该被os.killpg()调用终止。

虽然如果我用bash运行它;它确实为每个管道创建了一个新的流程组:

$ python -c "import os; print(os.getpgrp())"
25225
$ python -c "import os; print(os.getpgrp())"
25248