为什么python的多处理池get()函数有时是块,而不是其他块?

为什么python的多处理池get()函数有时是块,而不是其他块?,python,multiprocessing,Python,Multiprocessing,我正在使用python中的Multiprocessing.Pool,我不理解正在发生的事情。下面是一个虚拟版本,它展示了我的意思: from multiprocessing import Pool from time import sleep def f1(): for i in range(5): sleep(.1) print("f1:",i) print("f1 exiting") return('f1f1f1f1f1f1f1')

我正在使用python中的Multiprocessing.Pool,我不理解正在发生的事情。下面是一个虚拟版本,它展示了我的意思:

from multiprocessing import Pool
from time import sleep

def f1():
    for i in range(5):
        sleep(.1)
        print("f1:",i)
    print("f1 exiting")
    return('f1f1f1f1f1f1f1')

def f2():
    for i in range(10):
        sleep(.1)
        print("f2:",i)
    print("f2 exiting")
    return('f2f2f2ff2f2f2f2f2f')

pool = Pool(processes=2)

print('starting apply_async for p1, p2')
p1 = pool.apply_async(f1)
p2 = pool.apply_async(f2)
print('finished apply_async for p1, p2')


print('starting get() for p1, p2')
print(p1.get(timeout=10))
print(p2.get(timeout=10))
print('finished get() for p1, p2')


print('\n\n\ndone')
如果我运行此操作,f1和f2将同时运行并输出:

starting apply_async for p1, p2
finished apply_async for p1, p2
starting get() for p1, p2
f1: 0
f2: 0
f2: 1
f1: 1
f2: 2
f1: 2
f2: 3
f1: 3
f1: 4
f2: 4
f1 exiting
f1f1f1f1f1f1f1
f2: 5
f2: 6
f2: 7
f2: 8
f2: 9
f2 exiting
f2f2f2ff2f2f2f2f2f
finished get() for p1, p2
很明显,get并没有阻止程序其余部分的执行,当p1调用它时,它会立即转到p2.get

但是,如果我注意到f1略有变化:

from multiprocessing import Pool
from time import sleep

def f1():
    for i in range(5):
        sleep(1)
        print("f1:",i)
    print("f1 exiting")
    return('f1f1f1f1f1f1f1')

def f2():
    for i in range(10):
        sleep(.1)
        print("f2:",i)
    print("f2 exiting")
    return('f2f2f2ff2f2f2f2f2f')


pool = Pool(processes=1)

print('starting apply_async for p1')
p1 = pool.apply_async(f1)
print('finished apply_async for p1')

print('starting get() for p1')
print(p1.get(timeout=10))
print('finished get() for p1')

print('calling f2()')
f2()

print('\n\n\ndone')
我得到:

starting apply_async for p1
finished apply_async for p1
starting get() for p1
f1: 0
f1: 1
f1: 2
f1: 3
f1: 4
f1 exiting
f1f1f1f1f1f1f1
finished get() for p1
calling f2()
f2: 0
f2: 1
f2: 2
f2: 3
f2: 4
f2: 5
f2: 6
f2: 7
f2: 8
f2: 9
f2 exiting
因此,在本例中,p1.get是程序主要部分的阻塞。在这种情况下,如果我使用1个或2个进程,也没有什么区别

我明白了,这是因为在本例中,f2没有被一个池工作者调用,但我仍然感到困惑。更奇怪的是,如果我在第二种情况下切换f1和f2的顺序,比如:

pool = Pool(processes=1)

print('starting apply_async for p1')
p1 = pool.apply_async(f1)
print('finished apply_async for p1')

print('calling f2()')
f2()

print('starting get() for p1')
print(p1.get(timeout=10))
print('finished get() for p1')
当f2仍在执行时,它会启动f1的get:

starting apply_async for p1
finished apply_async for p1
calling f2()
f2: 0
f2: 1
f2: 2
f2: 3
f2: 4
f2: 5
f2: 6
f2: 7
f2: 8
f1: 0
f2: 9
f2 exiting
starting get() for p1
f1: 1
f1: 2
f1: 3
f1: 4
f1 exiting
f1f1f1f1f1f1f1
finished get() for p1
可以在f2:8和f2:9之间看到f1:0

这让我很困惑。在本例中,f2与池内容无关,所以当它第一次被调用时,它如何不阻塞呢


有人能澄清一下泳池发生了什么事吗?我已经读过文档,但它并没有真正为我澄清。

它在任何情况下都会阻塞。与第一个示例的第二个和第三个示例不同的是,您没有打印出p1.get和p2.get之间的任何内容,因此无法从打印输出中看出它是否阻塞。p2在调用apply_asyncf2时就开始运行,这就是为什么在p1仍在等待时从p2获取输出,但这与对p1.get的调用无关