【问题标题】:Python How to prevent multiprocessing zombies when the kernel is terminatedPython如何在内核终止时防止多处理僵尸
【发布时间】:2017-05-18 16:52:07
【问题描述】:

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

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

问题是工人通常需要工作几个小时。但有时在启动脚本后,我想更改一些代码并重新启动脚本。如果我等到工作完成,因为我使用了 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()

【问题讨论】:

  • “关闭内核”是什么意思?你实际发出的是哪个命令?
  • 事实上,我使用 Spyder IDE 并单击 Ipython 控制台的方形按钮“停止当前命令”或 Python 控制台的三角形按钮“终止当前进程”。或者,我直接关闭 Spyder。僵尸进程始终存在。我也使用过 Atom,如果我稍后运行脚本并关闭 Atom,情况也是如此。
  • 您使用的是哪个操作系统?
  • 啊... Windows :( 不过我以后会用linux来运行文件
  • @AkshatMahajan 我不相信“内核”是不正确的,因为它在问题中使用。 Spyder 使用 iPython/Jupyter,它利用各种内核 (github.com/jupyter/jupyter/wiki/Jupyter-kernels) 作为后端。

标签: python multiprocessing zombie-process


【解决方案1】:

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

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

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

在 Linux 上,您可以使用带有 -P 参数的 pkill 命令。 Pkill manpage.

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

import os
from signal import signal, SIGINT, SIGTERM

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

signal.signal(SIGTERM, handler)

这是一个 hack,我什至不确定它是否可以在 Windows 上运行。

【讨论】:

  • 非常感谢。所以似乎唯一的方法就是手动清理那些僵尸?我尝试了Taskkill,效果很好:) 目前,我不太了解SIGTERM 的代码,但我稍后会进行一些搜索。再次感谢!
  • 如果答案有用,请将其标记为正确,以便其他人可以轻松找到它。如果您的 IDE 允许自定义(Atom 允许),您可以添加快捷方式。如果您不完全了解 SIGTERM 替代方案,请远离它 :)。无论如何,这是一个黑客攻击。
  • 好的!非常感谢你! :) 抱歉迟到了。
猜你喜欢
  • 1970-01-01
  • 2013-06-05
  • 1970-01-01
  • 2022-01-03
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
  • 1970-01-01
相关资源
最近更新 更多