从Python多处理模块管理进程

时间:2014-10-21 13:12:17

标签: python multiprocessing

所以我以为我终于发帖了;管理Process工人的正确方法是什么?我曾尝试使用Pool,但我发现无法获得每个已完成流程的返回值。我尝试使用回调,但这也没有按预期工作。我应该自己使用active_children ()管理它们吗?

我的泳池代码:

from multiprocessing import *                                                                                      
import time
import random

SOME_LIST = []

def myfunc():
    a = random.randint(0,3)
    time.sleep(a)
    return a

def cb(retval):
    SOME_LIST.append(retval)

print("Starting...")

p = Pool(processes=8)
p.apply_async(myfunc, callback=cb)
p.close()
p.join()

print("Stopping...")
print(SOME_LIST)

我期待一个价值清单;但我得到的只是完成工作者工作的最后一项:

$ python multi.py 
Starting...
Stopping...
[3]

注意:答案不应该使用threading模块;这就是为什么:

  

在CPython中,由于Global Interpreter Lock,只有一个线程可以   一次执行Python代码(即使某些性能导向   图书馆可能会克服这个限制)。如果你想要你的   应用程序,以更好地利用计算资源   多核机器,建议您使用多处理。

1 个答案:

答案 0 :(得分:4)

你误解了apply_async的工作方式。它不会调用您在Pool中的每个进程中传递给它的函数。它只是在一个工作进程中调用该函数一次。因此,您所看到的结果是可以预期的。您有几种方法可以获得所需的行为:

from multiprocessing import Pool                                                                                   
import time
import random

SOME_LIST = []

def myfunc():
    a = random.randint(0,3)
    time.sleep(a)
    return a

def cb(retval):
    SOME_LIST.append(retval)

print("Starting...")

p = Pool(processes=8)
for _ in range(p._processes):
    p.apply_async(myfunc, callback=cb)
p.close()
p.join()

print("Stopping...")
print(SOME_LIST)

或者

from multiprocessing import Pool                                                                                      
import time
import random


def myfunc():
    a = random.randint(0,3)
    time.sleep(a)
    return a

print("Starting...")

p = Pool(processes=8)
SOME_LIST = p.map(myfunc, range(p._processes))
p.close()
p.join()

print("Stopping...")
print(SOME_LIST)

请注意,您还可以为更多调用apply_asyncmap,而不是池中的进程数。 Pool的想法是,无论您提交多少任务,它都会保证num_processes的整个生命周期内都会运行Pool个进程。因此,如果您创建一个Pool(8)并呼叫apply_async一次,您的八名工作人员中的一名将获得一项任务,而其他七名工作人员将处于闲置状态。如果你创建一个Pool(8)并调用apply_async 80次,那么80个任务将分发给你的8个工作人员,一次实际处理的任务不超过8个。