我正在尝试为我自己的目的实现这个多处理tutorial。起初我认为它不能很好地扩展,但是当我做了一个可重复的例子时,我发现如果项目列表超过124,它似乎永远不会返回答案。在x = 124
,它在.4秒内运行,但当我将其设置为x = 125
时,它永远不会完成。我在Windows 7上运行Python 2.7。
from multiprocessing import Lock, Process, Queue, current_process
import time
class Testclass(object):
def __init__(self, x):
self.x = x
def toyfunction(testclass):
testclass.product = testclass.x * testclass.x
return testclass
def worker(work_queue, done_queue):
try:
for testclass in iter(work_queue.get, 'STOP'):
print(testclass.counter)
newtestclass = toyfunction(testclass)
done_queue.put(newtestclass)
except:
print('error')
return True
def main(x):
counter = 1
database = []
while counter <= x:
database.append(Testclass(10))
counter += 1
print(counter)
workers = 8
work_queue = Queue()
done_queue = Queue()
processes = []
start = time.clock()
counter = 1
for testclass in database:
testclass.counter = counter
work_queue.put(testclass)
counter += 1
print(counter)
print('items loaded')
for w in range(workers):
p = Process(target=worker, args=(work_queue, done_queue))
p.start()
processes.append(p)
work_queue.put('STOP')
for p in processes:
p.join()
done_queue.put('STOP')
newdatabase = []
for testclass in iter(done_queue.get, 'STOP'):
newdatabase.append(testclass)
print(time.clock()-start)
print("Done")
return(newdatabase)
if __name__ == '__main__':
database = main(124)
database2 = main(125)
答案 0 :(得分:6)
OK!来自the docs:
警告如上所述,如果子进程已将项目放在队列中(并且没有 使用JoinableQueue.cancel_join_thread),然后该进程将不会终止直到所有 已缓冲的项目已刷新到管道。 这意味着如果您尝试加入该过程,除非您确定,否则可能会遇到死锁 已经消耗了所有已放入队列的项目。同样,如果 子进程是非守护进程,然后父进程在尝试时可能会在退出时挂起 加入所有非守护儿童。请注意,使用管理器创建的队列可以 没有这个问题。请参阅编程指南。
正如我之前在评论中提到的那样,代码尝试.join()
进程之前排除done_queue
队列 - 并且在以一种时髦的方式更改代码之后确保在done_queue
之前.join()
被耗尽,代码在一百万件项目中运行良好。
所以这是导航错误的一个例子,虽然相当模糊。至于为什么行为取决于传递给main(x)
的数字,它是不可预测的:它取决于内部如何进行缓冲。这样的乐趣; - )