如果父在Python中被杀死,则杀死子进程

时间:2014-08-28 06:27:29

标签: python multiprocessing

我从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)

但这似乎不起作用

4 个答案:

答案 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()