python 终止父进程但子进程离开
python kill parent process but child process left
虽然我尝试终止 python 进程,但通过 os.system
启动的子进程不会同时终止。
Killing child process when parent crashes in python 和
Python Process won't call atexit
(atexit 看起来不适用于信号)
这是否意味着我需要自己处理这种情况?如果是这样,这样做的首选方法是什么?
> 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
示例代码:
main.py
import os
os.system('python loop.py')
loop.py
import time
while True:
time.sleep(1000)
更新 1
我做了一些实验,找到了一个可行的版本,但仍然对逻辑感到困惑。
import os
import sys
import signal
import subprocess
def sigterm_handler(_signo, _stack_frame):
# it raises SystemExit(0):
print 'go die'
sys.exit(0)
signal.signal(signal.SIGTERM, sigterm_handler)
try:
# os.system('python loop.py')
# use os.system won't work, it will even ignore the SIGTERM entirely for some reason
subprocess.call(['python', 'loop.py'])
except:
os.killpg(0, signal.SIGKILL)
在您的示例中,kill -15 4792
将 SIGTERM
发送到 run.py
——它不会向 loop.py
(或其父级 shell)发送任何内容。 SIGTERM
默认情况下不会传播到进程树中的其他进程。
os.system('python loop.py')
至少启动两个进程shell和python
进程。你不需要它;使用 subprocess.check_call()
到 运行 没有隐式 shell 的单个子进程。顺便说一句,如果你的 .
os.killpg(0, SIGKILL)
向当前进程组发送SIGKILL
信号。 A 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
虽然我尝试终止 python 进程,但通过 os.system
启动的子进程不会同时终止。
Killing child process when parent crashes in python 和 Python Process won't call atexit (atexit 看起来不适用于信号)
这是否意味着我需要自己处理这种情况?如果是这样,这样做的首选方法是什么?
> 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
示例代码:
main.py
import os
os.system('python loop.py')
loop.py
import time
while True:
time.sleep(1000)
更新 1
我做了一些实验,找到了一个可行的版本,但仍然对逻辑感到困惑。
import os
import sys
import signal
import subprocess
def sigterm_handler(_signo, _stack_frame):
# it raises SystemExit(0):
print 'go die'
sys.exit(0)
signal.signal(signal.SIGTERM, sigterm_handler)
try:
# os.system('python loop.py')
# use os.system won't work, it will even ignore the SIGTERM entirely for some reason
subprocess.call(['python', 'loop.py'])
except:
os.killpg(0, signal.SIGKILL)
kill -15 4792
将 SIGTERM
发送到 run.py
——它不会向 loop.py
(或其父级 shell)发送任何内容。 SIGTERM
默认情况下不会传播到进程树中的其他进程。
os.system('python loop.py')
至少启动两个进程shell和python
进程。你不需要它;使用 subprocess.check_call()
到 运行 没有隐式 shell 的单个子进程。顺便说一句,如果你的
os.killpg(0, SIGKILL)
向当前进程组发送SIGKILL
信号。 A shell 为每个管道创建一个新的进程组(一个作业),因此父进程中的 (请参阅更新) .参见 How to terminate a python subprocess launched with shell=True。os.killpg()
对子进程没有影响
#!/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