Python多处理不会在基本异常上终止

时间:2017-05-05 06:47:23

标签: python exception-handling python-multiprocessing

使用多处理池运行时,我发现工作进程一直在超出抛出异常的位置运行。

请考虑以下代码:

import multiprocessing


def worker(x):
    print("input: " + x)
    y = x + "_output"
    raise Exception("foobar")
    print("output: " + y)
    return(y)


def main():

    data = [str(x) for x in range(4)]
    pool = multiprocessing.Pool(1)
    chunksize = 1
    results = pool.map(worker, data, chunksize)
    pool.close()
    pool.join()

    print("Printing results:")
    print(results)


if __name__ == "__main__":
    main()

输出结果为:

$ python multiprocessing_fail.py
input: 0
input: 1
input: 2
Traceback (most recent call last):
input: 3
  File "multiprocessing_fail.py", line 25, in <module>
    main()
  File "multiprocessing_fail.py", line 16, in main
    results = pool.map(worker, data, 1)
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 251, in map
    return self.map_async(func, iterable, chunksize).get()
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 558, in get
    raise self._value
Exception: foobar

正如您所看到的,工作进程永远不会超过raise Exception("foobar")到第二个打印语句。但是,它会一次又一次地在函数worker()的开头恢复工作。

我在文档中寻找了解释,但找不到任何解释。这是一个可能相关的SO问题:

Keyboard Interrupts with python's multiprocessing Pool

但这是不同的(关于键盘中断没有被主进程选中)。

另一个问题:

How to catch exceptions in workers in Multiprocessing

这个问题也有所不同,因为在它中主进程没有捕获任何异常,而在这里master确实捕获了异常(第16行)。更重要的是,在那个问题中,工作者没有超过异常(工作者只有一个可执行行)。

正在运行python 2.7

1 个答案:

答案 0 :(得分:0)

  

评论:池应该启动一个worker,因为代码有pool = multiprocessing.Pool(1)。

     
    

来自Documnentation:
    一个进程池对象,它控制可以提交作业的工作进程池

  
  

评论:一名员工多次运行worker()函数

     
    

来自文档:
    map(func, iterable[, chunksize])
    此方法将可迭代变为多个块,并将其作为单独的任务提交给流程池。

  

您的worker()单独的任务。将worker()重命名为task()有助于澄清什么是。

  

评论:我期望工作进程在异常处崩溃

确实,单独的任务,您的worker()死亡,Pool开始下一个任务。

您想要的是Pool.terminate()

  

来自文档:

     
    

terminate()
    立即停止工作流程而不完成未完成的工作。

  
  

问题:...我发现工作进程一直在超出抛出异常的点。

您将iteration data提交给Pool,因此Pool执行以下操作:
启动len(数据)工作人员

data = [str(x) for x in range(4)]

主要问题是:您希望用什么

raise Exception("foobar")