Python 多处理队列使代码在处理大数据时挂起

Dod*_*lei 5 python process multiprocessing large-data python-multiprocessing

我正在使用 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()
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,如果要放入队列的项目太大,进程就会挂起。output.put()如果我在运行后编写更多代码,它不会冻结,但该过程仍然不会停止。

当字符串达到 65500 个字符时,这种情况就会开始发生,具体取决于您的解释器,它可能会有所不同。

我知道mp.Queue有一个maxsize参数,但经过一些搜索,我发现它与队列的项目数量大小有关,而不是项目本身的大小。

有没有解决的办法?我需要在原始代码中放入队列的数据非常非常大......

GPh*_*ilo 2

您的队列已满,没有消费者可以清空它。

根据 的定义Queue.put

如果可选参数 block 为 True(默认值)且超时为 None(默认值),则根据需要进行阻止,直到有空闲槽可用。

假设生产者和消费者之间不存在死锁(并且假设您的原始代码确实有消费者,因为您的示例没有),最终生产者应该被解锁并终止。检查您的消费者的代码(或将其添加到问题中,以便我们查看)


更新

这不是问题,因为队列尚未指定 maxsize,因此 put 应该成功,直到内存耗尽。

这不是队列的行为。正如本票中所述这里阻塞的部分不是队列本身,而是底层管道。从链接的资源(“[]”之间的插入是我的):

队列的工作方式如下: - 当您调用queue.put(data)时,数据被添加到双端队列中,双端队列可以永远增长和缩小 - 然后线程从双端队列中弹出元素,并将它们发送出去,以便其他进程可以通过管道或 Unix 套接字(通过套接字对创建)接收它们。但是,这是重要的一点,管道和 unix 套接字的容量都是有限的(过去是 4k - 页大小 - 在旧版 Linux 内核上的管道,现在是 64k,unix 套接字在 64k-120k 之间,具体取决于可调节的 systcls) 。- 当你执行queue.get()时,你只需在管道/套接字上进行读取

[..]当大小[变得太大]时,写入线程会在写入系统调用上阻塞。并且由于在将项目出队之前执行连接[注意:那是你的process.join],所以你只是死锁,因为连接等待发送线程完成,并且由于管道/套接字已满,写入无法完成!如果您在等待提交者进程之前将项目出队,则一切正常。


更新2

我明白。但我实际上没有消费者(如果是我想的那样),只有当进程完成将其放入队列中时,我才会从队列中获取结果。

是的,这就是问题所在。这multiprocessing.Queue不是一个存储容器。您应该专门使用它来在“生产者”(生成进入队列的数据的进程)和“消费者”(“使用”该数据的进程)之间传递数据。正如您现在所知,将数据留在那里是一个坏主意。

如果我什至无法先将其放入队列中,如何才能从队列中获取该项目?

putget如果数据填满管道,则可以隐藏将数据放在一起的问题,因此您只需在“主”进程中为队列外的项目设置一个循环,get例如将它们附加到列表中。该列表位于主进程的内存空间中,不会堵塞管道。