我从python脚本中生成了5个不同的进程,如下所示:
p = multiprocessing.Process(target=some_method,args=(arg,))
p.start()
我的问题是,当某个父进程(主脚本)被杀死时,子进程继续运行。
当父母被杀时,有没有办法杀死这样产生的子进程?
编辑: 我试过这个:
p = multiprocessing.Process(target=client.start,args=(self.query_interval,))
p.start()
atexit.register(p.terminate)
但这似乎不起作用
答案 0 :(得分:17)
我自己也遇到过同样的问题,我已经得到了以下解决方案:
在致电p.start()
之前,您可以设置p.daemon=True
。然后在这里提到python.org multiprocessing
当进程退出时,它会尝试终止所有守护进程子进程。
答案 1 :(得分:4)
孩子不会被告知其父母的死亡,只会以其他方式运作。
但是,当进程终止时,其所有文件描述符都将关闭。如果选择管道进行读取,管道的另一端会收到通知。
因此,您的父级可以在生成进程之前创建管道(或者实际上,您可以将stdin设置为管道),并且子级可以选择该管道进行读取。当父结束关闭时,它将报告准备好阅读。这需要您的孩子运行主循环,或至少定期拨打电话进行选择。如果你不想这样做,你需要一些经理人来完成它,但是当那个被杀的时候,事情会再次破裂。
答案 2 :(得分:1)
如果您有权访问父pid,则可以使用类似的
import os
import sys
import psutil
def kill_child_proc(ppid):
for process in psutil.process_iter():
_ppid = process.ppid()
if _ppid == ppid:
_pid = process.pid
if sys.platform == 'win32':
process.terminate()
else:
os.system('kill -9 {0}'.format(_pid))
kill_child_proc(<parent_pid>)
答案 3 :(得分:0)
我的案例是使用 Queue
对象与子进程通信。无论出于何种原因,已接受答案中建议的 daemon
标志不起作用。这是一个最小的例子,说明在这种情况下如何让孩子们优雅地死去。
主要思想是每隔一秒左右暂停子工作执行并检查父进程是否还活着。如果它不存在,我们关闭队列并退出。
请注意,如果使用 SIGKILL
import ctypes, sys
import multiprocessing as mp
worker_queue = mp.Queue(maxsize=10)
# flag to communicate the parent's death to all children
alive = mp.Value(ctypes.c_bool, lock=False)
alive.value = True
def worker():
while True:
# fake work
data = 99.99
# submit finished work to parent, while checking if parent has died
queued = False
while not queued:
# note here we do not block indefinitely, so we can check if parent died
try:
worker_queue.put(data, block=True, timeout=1.0)
queued = True
except: pass
# check if parent process is alive still
par_alive = mp.parent_process().is_alive()
if not (par_alive and alive.value):
# for some reason par_alive is only False for one of the children;
# notify the others that the parent has died
alive.value = False
# appears we need to close the queue before sys.exit will work
worker_queue.close()
# for more dramatic shutdown, could try killing child process;
# wp.current_process().kill() does not work, though you could try
# calling os.kill directly with the child PID
sys.exit(1)
# launch worker processes
for i in range(4):
child = mp.Process(target=worker)
child.start()