多处理。在Linux/Python2.7上terminate()后池生成新子代?

多处理。在Linux/Python2.7上terminate()后池生成新子代?,python,linux,multiprocessing,subprocess,Python,Linux,Multiprocessing,Subprocess,我有一个我需要经常运行的可执行文件,带有不同的参数。为此,我使用多处理模块,按照给定的模式编写了一个小型Python(2.7)包装器 我的代码如下所示: try: logging.info("starting pool runs") pool.map(run_nlin, params) pool.close() except KeyboardInterrupt: logging.info("^C pressed") pool.terminate

我有一个我需要经常运行的可执行文件,带有不同的参数。为此,我使用多处理模块,按照给定的模式编写了一个小型Python(2.7)包装器

我的代码如下所示:

try:
     logging.info("starting pool runs")
     pool.map(run_nlin, params)
     pool.close()
 except KeyboardInterrupt:
     logging.info("^C pressed")
     pool.terminate()
 except Exception, e:
     logging.info("exception caught: ", e)
     pool.terminate()
 finally:
     time.sleep(5)
     pool.join()
     logging.info("done")
我的工作函数如下:

class KeyboardInterruptError(Exception): pass

def run_nlin((path_config, path_log, path_nlin, update_method)):
    try:
        with open(path_log, "w") as log_:
            cmdline = [path_nlin, path_config]
            if update_method:
                cmdline += [update_method, ]
            sp.call(cmdline, stdout=log_, stderr=log_)
    except KeyboardInterrupt:
        time.sleep(5)
        raise KeyboardInterruptError()
    except:
        raise
path\u config
是二进制程序配置文件的路径;例如,其中有运行程序的日期

当我打开包装时,一切看起来都很好。但是,当我按下
^C
时,包装器脚本似乎会在终止之前从池中启动另一个
numproc
进程。例如,当我在第1-10天启动脚本时,我可以在
ps aux
输出中看到二进制程序的两个实例正在运行(通常在第1天和第3天)。现在,当我按下
^C
时,包装器脚本退出,第1天和第3天的二进制程序消失,但第5天和第7天有新的二进制程序运行

所以在我看来,
Pool
似乎在最后死亡之前启动了另一个
numproc
进程

你知道这里发生了什么,我能做些什么吗?

上,《多处理模块》的作者杰西·诺勒(Jesse Noller)指出,处理键盘中断的正确方法是让子进程返回,而不是重新抛出异常。这允许主进程终止池

但是,如下面的代码所示,只有在运行了由
pool.map
生成的所有任务之后,主进程才会到达
块,键盘中断除外。这就是为什么(我相信)在按下
Ctrl-C
后,您会看到对辅助函数的额外调用,
run\nlin

一种可能的解决方法是,如果设置了
多处理.Event
,则测试所有辅助函数。如果已设置事件,则让工人尽早退出,否则,继续进行长期计算



运行脚本会产生以下结果:

% test.py
[WARNING/MainProcess] starting pool runs
[WARNING/PoolWorker-1] Running worker(0)
[WARNING/PoolWorker-2] Running worker(1)
[WARNING/PoolWorker-3] Running worker(2)
[WARNING/PoolWorker-4] Running worker(3)
这里按下Ctrl-C键;每个工作进程设置
终止
事件。我们真的只需要一个来设置它,但这是有效的,尽管效率很低

  C-c C-c[WARNING/PoolWorker-4] terminating is set
[WARNING/PoolWorker-2] terminating is set
[WARNING/PoolWorker-3] terminating is set
[WARNING/PoolWorker-1] terminating is set
现在运行由
pool.map
排队的所有其他任务:

[WARNING/PoolWorker-4] got the message... we're terminating!
[WARNING/PoolWorker-2] got the message... we're terminating!
[WARNING/PoolWorker-1] got the message... we're terminating!
[WARNING/PoolWorker-2] got the message... we're terminating!
[WARNING/PoolWorker-4] got the message... we're terminating!
[WARNING/PoolWorker-2] got the message... we're terminating!
[WARNING/PoolWorker-1] got the message... we're terminating!
[WARNING/PoolWorker-3] got the message... we're terminating!
最后,主进程到达除键盘中断之外的

[WARNING/MainProcess] ^C pressed
[WARNING/MainProcess] done: []

您使用的是windows还是类unix系统?Linux系统,Py2.7。更改标题和标记以反映this@unutbu:非常好的解决方案,是时候重温我自己的一些代码了+1.
[WARNING/MainProcess] ^C pressed
[WARNING/MainProcess] done: []