如何添加可用于多处理队列的进程池

时间:2019-06-20 14:42:19

标签: python multiprocessing

我在这里关注前面的问题:how to add more items to a multiprocessing queue while script in motion

我现在正在使用的代码:

import multiprocessing


class MyFancyClass:

    def __init__(self, name):
        self.name = name

    def do_something(self):
        proc_name = multiprocessing.current_process().name
        print('Doing something fancy in {} for {}!'.format(proc_name, self.name))


def worker(q):
    while True:
        obj = q.get()
        if obj is None:
            break
        obj.do_something()


if __name__ == '__main__':
    queue = multiprocessing.Queue()

    p = multiprocessing.Process(target=worker, args=(queue,))
    p.start()

    queue.put(MyFancyClass('Fancy Dan'))
    queue.put(MyFancyClass('Frankie'))
    # print(queue.qsize())
    queue.put(None)

    # Wait for the worker to finish
    queue.close()
    queue.join_thread()
    p.join()

现在,队列中有两个项目。如果我将两行替换为例如50个项目的列表...。如何启动POOL以允许进行许多处理。例如:

p = multiprocessing.Pool(processes=4)

那去哪儿了?我希望能够一次运行多个项目,尤其是当项目运行一会儿时。 谢谢!

1 个答案:

答案 0 :(得分:0)

通常,您或者都使用Pool Process(es)加Queue。两者混用是一种误用。 Pool已在幕后使用Queue(或类似机制)。

如果要使用Pool来执行此操作,请将代码更改为(将代码移至main函数,以实现性能并比在全局范围内运行更好地清理资源):

def main():
    myfancyclasses = [MyFancyClass('Fancy Dan'), ...] # define your MyFancyClass instances here
    with multiprocessing.Pool(processes=4) as p:
        # Submit all the work
        futures = [p.apply_async(fancy.do_something) for fancy in myfancyclasses]

        # Done submitting, let workers exit as they run out of work
        p.close()

        # Wait until all the work is finished
        for f in futures:
            f.wait()

if __name__ == '__main__':
    main()

可以使用.*map*的{​​{1}}方法(例如,尽量减少内存使用,将Pool重新定义为:

main

是的,从技术上讲,这两种方法在需要序列化未使用的返回值方面的开销都稍高一些,因此请将其返回给父进程。但是在实践中,此开销非常低(由于您的函数没有def main(): myfancyclasses = [MyFancyClass('Fancy Dan'), ...] # define your MyFancyClass instances here with multiprocessing.Pool(processes=4) as p: # No return value, so we ignore it, but we need to run out the result # or the work won't be done for _ in p.imap_unordered(MyFancyClass.do_something, myfancyclasses): pass ,因此返回的是return,该序列化为几乎没有内容)。这种方法的优点是,要打印到屏幕上,通常不想要从子进程中进行打印(因为它们最终将交错输出),因此您可以替换{ {1}}和None一起让父母来做,例如:

print

请注意,所有这些解决方案如何消除了编写自己的return函数或手动管理import multiprocessing class MyFancyClass: def __init__(self, name): self.name = name def do_something(self): proc_name = multiprocessing.current_process().name # Changed from print to return return 'Doing something fancy in {} for {}!'.format(proc_name, self.name) def main(): myfancyclasses = [MyFancyClass('Fancy Dan'), ...] # define your MyFancyClass instances here with multiprocessing.Pool(processes=4) as p: # Using the return value now to avoid interleaved output for res in p.imap_unordered(MyFancyClass.do_something, myfancyclasses): print(res) if __name__ == '__main__': main() 的麻烦,因为worker帮了您大忙。


使用Queue的替代方法可以在结果可用时有效地对其进行处理,同时允许您选择随行提交新工作(基于结果或基于外部信息):

Pool