为什么在实际处理的时候输出显示pool被关闭了多次?

Why does the output show that pool is closed multiple times when it is actually processing?

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

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 module, when a new process is created, it imports the __main__ module*. Basically it runs the same file that was passed to the main thread, but any if __name__ == '__main__': blocks will fail because __name__ will be something else. Then it passes which function to call and what arguments to call it with via pickle.

基本上,当您调用 with Pool(processes=4) as pool: 时,4 个子进程都会启动并执行打印语句。

您的第二个问题“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的区别。