将SIGINT / ^ C传递给池中的子项?

时间:2012-07-02 19:05:07

标签: python process multiprocessing pool python-2.x

我有以下代码(仅测试关于Pool类的一些假设):

#!/usr/bin/env python
from time import sleep
from multiprocessing import Pool

def run_process(args):
    print "Sleeping %d seconds" % (args * 2)
    sleep(args * 2)
    print "Slept %d seconds" % (args * 2)

def main():
    test = [1,2,3,1,2,3,1,2,3]
    pool = Pool()
    pool.map_async(run_process, test).get()

if __name__ == '__main__':
    main()

最终test将成为要传递给run_process每次调用的参数列表,以便它生成一个命令(即一个单独的进程)。

现在当我按 Ctrl + C 时,遗憾的是它甚至没有拆除直接子进程(从文档中听起来像Pool创建的那样简单的儿童过程)。终端上发生的事情(Ubuntu 10.04,Python 2.6.5,如果这很重要)是每当我按下它时我都会看到回显的^C,但是当所有孩子都退出时,父母也没有及时死亡“工作”(即睡觉)也不能在不杀死父进程的情况下收回终端。

如何调整我的脚本以便它可以拆除直接的子节点(以及后来生成的命令)?我想我正在尝试的是使用信号处理程序中的multiprocessing.Pool.close()multiprocessing.Pool.terminate()

N.B。:我故意在这里使用流程而不是线程,所以如果解决方案考虑到这一点,我会很感激。


在阅读this question的答案之后,我尝试了一件事,但它遇到了同样的问题:

#!/usr/bin/env python
from signal import signal
from time import sleep
from multiprocessing import Pool

def init_worker():
    import signal
    signal(signal.SIGINT, signal.SIG_IGN)

def run_process(args):
    print "Sleeping %d seconds" % (args * 2)
    sleep(args * 2)
    print "Slept %d seconds" % (args * 2)

def main():
    test = [1,2,3,1,2,3,1,2,3]
    try:
        pool = Pool()
        pool.map_async(run_process, test).get()
    except KeyboardInterrupt:
        pool.terminate()
        pool.wait()

if __name__ == '__main__':
    main()

添加一个非常大的超时(作业可以运行几周,所以超时必须足够大以覆盖它)到Pool.get()似乎允许我使用 Ctrl + < kbd> C ,虽然输出有些令人困惑:

Traceback (most recent call last):
  File "./test.py", line 26, in <module>
    main()
  File "./test.py", line 23, in main
    pool.wait()
AttributeError: 'Pool' object has no attribute 'wait'

摆脱try / except后,追溯看起来“更自然”。因此,诀窍是将原始脚本pool.map_async(run_process, test).get()中的行更改为pool.map_async(run_process, test).get(999999),其中999999的超时时间足以满足您的目的。

0 个答案:

没有答案