我无法理解如何将队列实现到下面的多处理示例中。基本上,我希望代码:
1)产生2个过程(完成)
2)将我的id_list分成两部分(完成)
3)让每个进程遍历列表打印出每个项目,并且仅在完成列表时关闭。我知道我必须实现某种类型的排队系统,并将其传递给每个工作者,但我不知道该怎么做。任何帮助将不胜感激。
from multiprocessing import Pool,Queue
id_list = [1,2,3,4,5,6,7,8,9,10]
def mp_worker(record):
try:
print record
sleep(1)
except: pass
print "worker closed"
def mp_handler():
p = Pool(processes = 2) #number of processes
p.map(mp_worker, id_list) #devides id_list between 2 processes, defined above
p.close()
p.join()
mp_handler()
注意 - 代码打印出“工人关闭”10次。我喜欢这个陈述只打印两次(每个工人一次,每个工人打印出来自id_list的5个数字)
答案 0 :(得分:3)
这对我有用(在Python 3上)。我没有使用Pool,而是生成了我自己的两个进程:
self.parent.get_screen('INSERTSCREENNAMEHERE').main_run()
虽然要处理的元素的长度是硬编码的。但它可能是mp_worker方法的第二个输入参数。
答案 1 :(得分:0)
你在那里的print语句会误导你 - 工作进程不会在函数结束时终止。实际上,工作进程在池关闭之前一直处于活动状态。此外,multiprocessing
已经负责将列表拆分为块并为您排队每个任务。
至于你的另一个问题,如果你想在整个列表完成时触发异步事件,通常会将回调传递给map_async
。每个块调用一次会对内部进行一些调整,但是如果你真的想要你可以:
def mapstar_custom(args):
result = list(map(*args))
print "Task completed"
return result
...
pool._map_async(f, x, mapstar_custom, None, None, None).get()
编辑:我们似乎在混淆术语。当我说工人时我指的是池产生的过程,而你似乎意味着Selenium从这些过程产生的过程(这不在你的问题中)。只打开一次webdriver就很容易了:如果你有pool.map(module.task, ...)
,那么只需module.py
:
# ... selenium init here ...
def task(...):
# ... use webdriver ...
模块只会由池工作人员导入一次,无论您派遣该任务多少次。所以顶级init只会发生一次。
答案 2 :(得分:0)
使用“池和队列”解决此问题的一种方法是
from time import sleep
from multiprocessing import Pool,Queue
id_list = [1,2,3,4,5,6,7,8,9,10]
def mp_worker(q):
try:
print(q.get())
sleep(.1)
except: pass
print ("worker closed")
if __name__ == "__main__":
q = Queue()
p = Pool(processes = 2) #number of processes
for x in id_list:
q.put(x)
p.map(mp_worker, id_list) #devides id_list between 2 processes, defined above
您必须在代码的主要部分中按 put 将vaule添加到Quene中,并在函数中通过 get
从Queue中读取值