繁体   English   中英

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

[英]Kill Child Process if Parent is killed in Python

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

但这似乎不起作用

我自己也遇到过同样的问题,我有以下解决方案:

在调用p.start()之前,您可以设置p.daemon=True 然后正如这里提到的python.org 多处理

当一个进程退出时,它会尝试终止其所有守护进程。

孩子不会收到父母死亡的通知,它只会以另一种方式工作。

但是,当一个进程终止时,它的所有文件描述符都将关闭。 如果管道的另一端选择了要读取的管道,则会通知管道的另一端。

因此,您的父母可以在生成进程之前创建一个管道(或者实际上,您可以将 stdin 设置为管道),而孩子可以选择它进行阅读。 当父端关闭时,它将报告准备好阅读。 这需要您的孩子运行主循环,或者至少定期调用选择。 如果你不想那样做,你需要一些管理器进程来做,但是当那个进程被杀死时,事情又会崩溃。

如果您有权访问父 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>)

我的情况是使用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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM