摘要
代码
测试我写的以下内容,在Windows中使用python 2.7.10:
from multiprocessing.dummy import Pool as thPool
from time import sleep
def funct(n):
#print "{"+str(n)+"}",
#print "|"+str(len(li))+"|",
if n % 2 == 0:
return n
elif n % 3 == 0:
li.append(12)
elif n % 5 == 0:
li.append(14)
#sleep(.25)
if __name__ == "__main__":
P = thPool(4)
li = [1,2,3,4,5,6,7,8,9]
lf=(i for i in P.imap_unordered(funct,li) if i is not None)
#print lf
for m in lf:
print "("+str(m)+")",
#sleep(.25)
我所期望的是,没有特别的顺序,偶数(2,4,6,8),两个12,一个14。
结果
我多次跑了以上。我每次都得到不同的结果:
我假设迭代器在附加列表之前完成。我在 funct 中放置了一个调试打印语句来显示全局列表 li 的大小,我得到了:
在竞争激烈的情况下,我也开始制造延迟,但这似乎对可预测性没有影响。
问题
答案 0 :(得分:1)
另外,遗憾的是,在这种情况下,我认为你不能使用imap_unordered()
。我认为您看到的行为是由于imap_unordered
有时会到达可迭代的末尾,并且在之前将其他项目放在列表中之前停止分发。
答案 1 :(得分:1)
在这种情况下,请勿使用multiprocessing.Pool.imap_unordered
。有办法使它发挥作用,但它们是丑陋和脆弱的。使用生产者 - 消费者模式,消费者偶尔会充当生产者。
from multiprocessing.dummy import Process, Queue
def process(inq, outq):
while True:
n = inq.get()
try:
if n % 2 == 0:
outq.put(n) # Queue up for printing
elif n % 3 == 0:
inq.put(12) # Queue up for future processing
elif n % 5 == 0:
inq.put(14) # Queue up for future processing
finally:
inq.task_done()
def printer(q):
while True:
m = q.get()
try:
print "("+str(m)+")",
finally:
q.task_done()
def main():
workqueue = Queue()
printqueue = Queue()
printworker = Process(target=printer, args=(printqueue,))
printworker.daemon = True
printworker.start()
for i in range(4):
processor = Process(target=process, args=(workqueue, printqueue))
processor.daemon = True
processor.start()
li = [1,2,3,4,5,6,7,8,9]
for x in li:
workqueue.put(x) # optionally, put all items before starting processor threads so initial work is processed strictly before generated work
workqueue.join() # Wait for all work, including new work, to be processed
printqueue.join() # Then wait for all the results to be printed
if __name__ == '__main__':
main()