从multiprocessing.Pool调用的函数退出的正确方法?

时间:2018-10-09 19:11:59

标签: python multiprocessing pool

如何从名为multiprocessing.Pool的函数中退出

这是我使用的代码的示例,当我在终端中将其用作脚本时将条件从函数worker退出时,它会暂停并且不退出。

def worker(n):
    if n == 4:
        exit("wrong number")  # tried to use sys.exit(1) did not work
    return n*2

def caller(mylist, n=1):
    n_cores = n if n > 1 else multiprocessing.cpu_count()
    print(n_cores)
    pool = multiprocessing.Pool(processes=n_cores)
    result = pool.map(worker, mylist)
    pool.close()
    pool.join()
    return result

l = [2, 3, 60, 4]
myresult = caller(l, 4)

2 个答案:

答案 0 :(得分:1)

正如我所说,我认为您不能从工作进程中退出运行主脚本的任务。

您还没有完全解释为什么要这么做,所以这个答案只是个猜测,但也许是提出一个自定义Exception并以显式{{1}处理它},如下所示是解决此限制的一种可接受的方法。

except

运行时显示输出:

import multiprocessing
import sys

class WorkerStopException(Exception):
    pass

def worker(n):
    if n == 4:
        raise WorkerStopException()
    return n*2

def caller(mylist, n=1):
    n_cores = n if n > 1 else multiprocessing.cpu_count()
    print(n_cores)
    pool = multiprocessing.Pool(processes=n_cores)
    try:
        result = pool.map(worker, mylist)
    except WorkerStopException:
        sys.exit("wrong number")
    pool.close()
    pool.join()
    return result

if __name__ == '__main__':
    l = [2, 3, 60, 4]
    myresult = caller(l, 4)

4 wrong number 是我的系统拥有的CPU数量。)

答案 1 :(得分:1)

pool.map的作用是,它将仅在所有任务完成后 引发子进程的异常。但是您的注释听起来就像您需要在任何进程中检测到错误值后立即中止所有处理。这样,pool.apply_async就可以了。

pool.apply_async提供了error_callbacks,您可以使用它来终止池。像pool.map变体一样,将逐项而不是逐块地为工作者提供工作,因此您有机会提前退出每个已处理的参数。

我基本上是在重复使用here的答案:

from time import sleep
from multiprocessing import Pool

def f(x):
    sleep(x)
    print(f"f({x})")
    if x == 4:
        raise ValueError(f'wrong number: {x}')
    return x * 2

def on_error(e):
    if type(e) is ValueError:
        global terminated
        terminated = True
        pool.terminate()
        print(f"oops: {type(e).__name__}('{e}')")


def main():
    global pool
    global terminated

    terminated = False

    pool = Pool(4)
    results = [pool.apply_async(f, (x,), error_callback=on_error)
               for x in range(10)]
    pool.close()
    pool.join()

    if not terminated:
        for r in results:
            print(r.get())


if __name__ == '__main__':
    main()

输出:

f(0)
f(1)
f(2)
f(3)
f(4)
oops: ValueError('wrong number: 4')

Process finished with exit code 0