我正在使用 python 的多重处理来分析一些大文本。经过几天尝试找出我的代码挂起的原因(即进程没有结束)后,我能够使用以下简单代码重新创建问题:
import multiprocessing as mp
for y in range(65500, 65600):
print(y)
def func(output):
output.put("a"*y)
if __name__ == "__main__":
output = mp.Queue()
process = mp.Process(target = func, args = (output,))
process.start()
process.join()
正如您所看到的,如果要放入队列的项目太大,进程就会挂起。
如果我之后编写更多代码,它不会冻结output.put()
它会运行,但该过程永远不会停止。
当字符串达到 65500 个字符时,这种情况就会开始发生,具体取决于您的解释器,它可能会有所不同。
我知道mp.Queue
has a maxsize
参数,但做了一些搜索,我发现它与队列的项目数量大小有关,而不是项目本身的大小。
有没有解决的办法?
我需要在原始代码中放入队列的数据非常非常大......
您的队列已满,没有消费者可以清空它。
从定义Queue.put https://docs.python.org/2/library/multiprocessing.html#multiprocessing.Queue.put:
如果可选参数 block 为 True(默认值)且超时为 None(默认值),则根据需要进行阻止,直到有空闲槽可用。
假设生产者和消费者之间不存在死锁(并且假设您的原始代码确实有消费者,因为您的示例没有),最终生产者应该被解锁并终止。检查您的消费者的代码(或将其添加到问题中,以便我们查看)
Update
这不是问题,因为队列尚未指定 maxsize,因此 put 应该会成功,直到内存耗尽。
这不是队列的行为。正如本文中详细阐述的ticket https://bugs.python.org/issue8426,这里阻塞的部分不是队列本身,而是底层的管道。从链接的资源(“[]”之间的插入是我的):
队列的工作方式如下:
- 当你调用queue.put(data)时,数据被添加到双端队列中,双端队列可以永远增长和收缩
- 然后一个线程从双端队列中弹出元素,并发送它们,以便其他进程可以通过管道或 Unix 套接字(通过套接字对创建)接收它们。但是,这是重要的一点,管道和 unix 套接字的容量都是有限的(过去是 4k - 页大小 - 在旧版 Linux 内核上的管道,现在是 64k,unix 套接字在 64k-120k 之间,具体取决于可调节的 systcls) 。
- 当你执行queue.get()时,你只需在管道/套接字上进行读取
[..]当大小[变得太大]时,写入线程会在写入系统调用上阻塞。
并且由于在将项目出列之前执行了连接[注意:这是您的process.join
],你只是死锁,因为连接等待发送线程完成,并且由于管道/套接字已满而写入无法完成!
如果您在等待提交者进程之前将项目出队,则一切正常。
Update 2
我明白。但我实际上没有消费者(如果是我想的那样),只有当进程完成将其放入队列中时,我才会从队列中获取结果。
是的,这就是问题所在。这multiprocessing.Queue
不是储存容器。您应该专门使用它来在“生产者”(生成进入队列的数据的进程)和“消费者”(“使用”该数据的进程)之间传递数据。正如您现在所知,将数据留在那里是一个坏主意。
如果我什至无法先将其放入队列中,如何才能从队列中获取该项目?
put
and get
如果数据填满了管道,就隐藏了将数据放在一起的问题,因此您只需在“主”进程中设置一个循环即可get
将项目移出队列,例如将它们附加到列表中。该列表位于主进程的内存空间中,不会堵塞管道。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)