Python多处理不会因基本异常而终止

Python多处理不会因基本异常而终止,python,exception-handling,python-multiprocessing,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)]

当使用多处理池运行时,我发现工作进程一直运行到抛出异常的点之后

考虑以下代码:

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
$python多处理\u fail.py
输入:0
输入:1
投入:2
回溯(最近一次呼叫最后一次):
投入:3
文件“multiprocessing_fail.py”,第25行,在
main()
文件“multiprocessing_fail.py”,第16行,主
结果=pool.map(工作者,数据,1)
文件“/usr/lib/python2.7/multiprocessing/pool.py”,第251行,在地图中
返回self.map\u async(func,iterable,chunksize).get()
get中的文件“/usr/lib/python2.7/multiprocessing/pool.py”,第558行
提升自我价值
例外:foobar
如您所见,辅助进程从未超出第二个print语句的
raiseexception(“foobar”)
。但是,它会在函数worker()的开头一次又一次地恢复工作

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

但这是不同的(关于主进程没有拾取键盘中断)

另一个问题:

这个问题也不同,因为在这里主进程不捕获任何异常,而在这里主进程捕获异常(第16行)。更重要的是,在这个问题中,worker没有运行过异常(worker只有一个可执行行)

我正在运行Python2.7


注释:池应该启动一个工作进程,因为代码具有Pool=multiprocessing.Pool(1)

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


注释:一个工作者正在多次运行worker()函数

来自文档:
map(func,iterable[,chunksize])

此方法将iterable拆分为若干块,并将其作为独立任务提交给进程池

data = [str(x) for x in range(4)]
您的
worker()
单独的任务。将您的
worker()
重命名为
task()
有助于澄清问题

注释:我希望工作进程在异常时崩溃

确实如此,单独的任务,您的
工作者()
死亡,
开始下一个任务

您需要的是
Pool.terminate()

来自文档:

terminate()

立即停止工作进程而不完成未完成的工作


问题:。。。我发现工作进程一直运行到抛出异常的点之后

您将
迭代数据
交给
,因此
执行它必须执行的操作:
启动len(数据)工作线程

data = [str(x) for x in range(4)]
主要问题是:你希望从中得到什么

raise Exception("foobar")

@jordanm的可能副本感谢您的快速响应!我读了那个问题,发现它和我的不同。编辑以显示差异。它似乎没有运行,但通过了异常。字符串“output:”从不打印。在异常被抛出并消失后,它似乎只是产生了一个新的工作进程。如果您希望整个脚本在子进程中出现异常后消失,则需要检测它并退出主进程。@jordanm我让工作进程打印其id(使用multiprocessing.current_process())并且它打印相同的辅助进程id。它是经过异常的同一个辅助进程。池应该启动一个辅助进程,因为代码具有
Pool=multiprocessing.Pool(1)
。一个worker正在多次运行worker()函数(并且多次命中异常)。我所期望的是工作进程在异常时崩溃,因为它是一个未处理的异常。不幸的是,文档中没有提到这种情况。注释:池应该启动一个worker,因为代码具有Pool=multiprocessing.Pool(1)。从文档中:
一个进程池对象,它控制作业可以提交到的工作进程池。
从文档中的下一行:
进程是要使用的工作进程数。
和调用:
类多处理.pool([processs[,initializer[,initargs[,maxstasksperchild]]]]
。因此应该只启动一个workercomment:它确实启动了,单独的任务,您的worker()死亡,而池启动下一个任务。函数worker()是一个函数对象,不能死亡。进程可以死亡。事实上,worker进程(如您所指出的,与worker()函数不同)不死是这里的主要问题。