为什么输出在实际处理池时显示多次关闭池?

问题描述

为什么输出在实际处理池时显示池已关闭

res.get()是阻止多处理的阻塞操作吗?

为什么打印Now the pool is closed and no longer available 5次?

from multiprocessing import Pool,TimeoutError
import time
import os

def f(x):
    time.sleep(5)
    return x*x

if __name__ == '__main__':
    # start 4 worker processes
    with Pool(processes=4) as pool: 
        for i in range(5):
            # evaluate "f(20)" asynchronously
            res = pool.apply_async(f,(20,))      # runs in *only* one process
            print(res.get())

    
# exiting the 'with'-block has stopped the pool
print("Now the pool is closed and no longer available")

输出

Now the pool is closed and no longer available
Now the pool is closed and no longer available
Now the pool is closed and no longer available
Now the pool is closed and no longer available
400
400
400
400
400
Now the pool is closed and no longer available

解决方法

在python的multiprocessing模块中,创建新进程时,它将导入__main__模块*。基本上,它运行与传递给主线程的文件相同的文件,但是任何if __name__ == '__main__':块都将失败,因为__name__将是其他东西。然后,它通过pickle传递要调用的函数和要调用的参数。

基本上,当您调用with Pool(processes=4) as pool:时,四个子进程分别启动并执行print语句。

对第二个问题“ res.get()是否是阻止操作”的回答是“是”。您应该将所有工作提交给处理池,以便在等待结果之前开始处理。

移动打印语句并将工作提交与结果检索分开可能看起来像这样:

from multiprocessing import Pool,TimeoutError
import time
import os

def f(x):
    time.sleep(5)
    return x*x

if __name__ == '__main__':
    # start 4 worker processes
    with Pool(processes=4) as pool:
        future_results = []
        for i in range(5):
            # evaluate "f(20)" asynchronously
            future_results.append(pool.apply_async(f,(20,)))
        #get results after submitting all work
        for res in future_results:
            print(res.get())

    #move this inside "if __name__ == '__main__':" so it isn't executed in child processes.
    # exiting the 'with'-block has stopped the pool
    print("Now the pool is closed and no longer available")

*在Unix上,其功能有所不同。这就是文档中提到的Spawn和Fork之间的区别。