当我尝试杀死python进程时,通过子进程启动的子进程os.system
不会同时终止。
当父进程在python中崩溃时杀死子进程,而Python进程不会调用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)
我做了一些实验,找到了可行的版本,但仍然对逻辑感到困惑。
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
(或它的父外壳)。SIGTERM
默认情况下不会传播到进程树中的其他进程。
os.system('python loop.py')
启动至少两个进程的shell和python
进程。您不需要它;使用subprocess.check_call()
,在没有隐式外壳的情况下运行单个子进程。顺便说一句,如果您的子进程是Python脚本;考虑导入它并运行相应的功能。
os.killpg(0, SIGKILL)
发送SIGKILL
信号到当前的进程组。 Shell为每个管道创建一个新的进程组(作业),因此 (请参阅更新)。请参阅如何终止由shell = True启动的python子进程。os.killpg()
父级中的 in对子级没有影响
#!/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
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句