Python多处理队列行为

时间:2016-03-05 04:30:45

标签: python python-multiprocessing

我有这段代码:

<script>
  hbspt.forms.create({ 
    portalId: '2089699',
    formId: '287337b2-e8a6-4eaa-b293-bbd3d3622d8a'
  });
</script>

完美无缺。但是当我def f(x, y): def _f(x, y, queue): res = get_data(x, y) queue.put(res) q = Queue() p = Process(target=_f, args=(x, y, q)) p.start() res = q.get() p.join() return res 之后res = q.get()这样做时:

p.join()

对于有些大的数据(例如,数百个JSON数组元素),它将挂起q = Queue() p = Process(target=_f, args=(x, y, q)) p.start() p.join() return q.get()

为什么?

1 个答案:

答案 0 :(得分:0)

您可能正在遇到比赛状况。如果您想查看multiprocessing.Queue的来源,您会注意到它使用multiprocessing.Pipethreading.Thread来在multiprocessing.Process实例之间进行通信。因此,当您调用Queue.put时,实际上是在要求上述线程使用Process创建的Connection.send将对象写入其他Pipe。当您致电Queue.get时,实际上是在消费通过Connection.recv接收的数据,这些数据构成了Pipe的另一端。

现在,如果深入研究multiprocessing.Pipe和它创建的Connection实例,您会发现它们使用OS低级接口来实现其大多数功能。但是,通过使用这样的接口,编写者必须遵守一个上限,即它可以向Connection.send馈送多少数据,而无需另外的ProcessThread调用各自的Connection.recv

在您的特定情况下,Process的{​​{1}}会在_f返回时立即结束(即,在您“问” queue.put(res)以写{{1 }})。阻止Thread完成的唯一事情是待处理的res;之后,它是免费的。如果对象较小并且遵守操作系统限制,则Process将立即返回,并且整个过程将完成。另一方面,如果对象大于操作系统限制,则Connection.send将阻止等待Conneciton.send为剩余数据释放一些空间。但是,这永远不会发生,因为在您调用Connection.send之后立即调用Connection.recv,它将阻塞直到Process.start结束;只有在您致电Process.join之后才会出现的结尾;仅在Process返回之后才会发生的呼叫;然后我们关闭了死锁链。