Python如何在内核终止时阻止多处理僵尸

时间:2017-05-18 16:52:07

标签: python multiprocessing zombie-process

最近我在Python中使用多处理时遇到了僵尸进程的问题。

我有一个脚本可以创建多个进程(工作程序)以及另一个进程(打印机)。工作人员会将msgs生成队列,打印机需要打印队列中的所有消息。

问题是通常工人需要工作几个小时。但有时在启动脚本后,我想更改一些代码并重新启动脚本。如果我等到作业结束,那么因为我使用join(),所以不会有僵尸。但是如果我直接关闭内核(因为ctrl + C对我的spyder不起作用),所有进程(僵尸)仍在工作。

我尝试使用os.ppid,但似乎ppid没有改变。 我试过p.daemon = True,但它既不起作用。

所以我想问一下是否有办法确保如果我关闭内核,所有进程都会自行终止,并且系统中没有僵尸。

谢谢,示例代码是:

from multiprocessing import Process, Queue
import time

def f(num, q):
    for i in range(100):
        q.put('f: num=%d\n'% (num,))
        time.sleep(10)
def g(q, filename):
    while True:
        with open(filename, 'a') as f:
            if q.qsize() > 0:
                item = q.get()
                if item == None:
                    break
                else:
                    f.write(item)
def main():
    filename = './log.txt'
    q = Queue()
    workers = [Process(target=f, args=(i,q)) for i in range(10)]
    printer = Process(target=g, args=(q,filename))
    for p in workers:
        p.daemon = True
        p.start()
    printer.daemon = True
    printer.start()
    for p in workers:
        p.join()
    q.put(None)
    printer.join()
if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:0)

子进程未被释放,因为父进程被突然终止而没有清理的可能性。因此,daemon标志没用。

我不会终止带有IDE的子进程,因为它可能没有考虑这样的用例。我宁愿依赖操作系统设施。

在Windows上,您可以将Taskkill命令与/T参数一起使用。请参阅taskkill documentation

在Linux上,您可以将pkill命令与-P参数一起使用。 Pkill manpage

最后一种方法是拦截SIGTERM信号并将其重新路由为SIGINT。但我不建议这样做。

import os
from signal import signal, SIGINT, SIGTERM

def handler(*_):
    os.kill(os.pid, SIGINT)

signal.signal(SIGTERM, handler)

这是一个黑客,我甚至不确定它是否适用于Windows。