我在这里关注前面的问题: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)
那去哪儿了?我希望能够一次运行多个项目,尤其是当项目运行一会儿时。 谢谢!
答案 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