我正在使用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
有一个maxsize
参数,但是进行一些搜索后发现,它与队列中项目数的大小有关,而不是项目本身的大小。
有没有解决的办法?我需要在原始代码中放入Queue的数据非常大...
您的队列已满,没有任何消费者可以清空它。
从定义Queue.put
:
如果可选参数块为True(默认值),并且超时为无(默认值),则如有必要,请阻塞,直到有可用的插槽可用。
假设生产者和使用者之间没有死锁(并且假设您的原始代码确实有使用者,因为您的示例没有),那么最终应该解除生产者并终止生产者。检查您消费者的代码(或将其添加到问题中,以便我们查看)
这不是问题,因为没有给队列一个maxsize,所以放置应该成功,直到用完内存。
这不是队列的行为。如该票证中所述,此处阻塞的部分不是队列本身,而是底层管道。从链接的资源(“ []”之间的插入是我的):
队列的工作方式如下:-调用queue.put(data)时,数据被添加到双端队列,该双端队列可以永远增长和收缩-然后线程从双端队列弹出元素,并将其发送出去,以便其他进程可以通过管道或Unix套接字(通过套接字对创建)接收它们。但是,这很重要,管道和unix套接字的容量都是有限的(以前是4k-页面大小-在较旧的Linux内核上用于管道,现在是64k,unix套接字在64k-120k之间,具体取决于可调systcls) 。-当您执行queue.get()时,您只需在管道/插座上进行读取
[..]当大小[变得太大]时,写线程在写syscall上阻塞。而且由于联接是在出队项[注:这是您的
process.join
]之前执行的,所以您就陷入僵局,因为联接等待发送线程完成,并且由于管道/套接字已满,写入无法完成!如果您在等待提交程序之前将项目出队,则一切正常。
我明白。但是我实际上没有消费者(如果这就是我的想法),我只会在流程完成将其放入队列后才从队列中获取结果。
是的,这就是问题所在。该multiprocessing.Queue
不是一个储存容器。您应该专门将其用于在“生产者”(生成进入队列的数据的过程)和“消费者”(“使用”该数据的过程)之间传递数据。如您所知,将数据留在这里是个坏主意。
如果我什至不能先把物品放到队列里怎么办?
put
并get
避免了在数据填满管道时将数据放在一起的问题,因此您只需要在“主”流程中为循环中的get
项目设置一个循环,例如,将其追加到列表中。该列表位于主进程的内存空间中,不会阻塞管道。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句