Python--从非空的multiprocessing.Queue中获取Queue.Empty异常

4 投票
2 回答
2836 浏览
提问于 2025-04-16 22:45

我遇到的问题和很多Python用户正好相反——我的程序使用的CPU太少了。我之前得到过帮助,把程序改成了多进程,这样可以利用我工作电脑的四个核心,确实看到了性能的提升。但是,这种提升有点不稳定。我的程序在运行的时候,CPU的使用率似乎会逐渐下降——即使我同时运行了六个进程。通过添加一些调试信息,我发现这是因为我创建的一些进程(它们本来应该一直运行到完成)提前结束了。进程运行的主要部分是一个无限循环,唯一的退出方式是这个代码块:

try:
    f = filequeue.get(False)
except Empty:
    print "Done"
    return

在创建子进程之前,filequeue已经被填充,所以它肯定不是空的。所有进程应该在队列真正空的时候大致同时退出。我尝试在Queue.get调用中添加一个非零的超时参数(0.05),但这并没有解决问题。为什么我会从一个非空的队列中得到Queue.empty的异常呢?

2 个回答

2

我遇到过类似的问题,通过实验发现,而不是看文档,即使队列不为空,调用 get(False) 也可能会错误地抛出 Empty 的错误。在我的使用场景中,工作者在队列里没有工作时必须退出,所以 get(True) 这个选项是行不通的。

我的解决办法是这样的:我发现如果在 "except Empty:" 这个块里,检查一下队列是否真的为空,效果就很好——只有当队列真的空的时候,empty() 才会返回 True。

我使用的是 Python 2.7。

3

我建议使用 filequeue.get(True),而不是 filequeue.get(False)。这样做会让队列在有更多元素之前一直等待。

不过,一旦处理完最后一个元素,它就会一直等待下去,永远不会结束。

为了避免这个问题,主程序可以在每个队列的末尾添加一个特殊的“哨兵”对象。当工作线程看到这个特殊对象时,就会停止工作(而不是依赖队列是否为空来判断)。

撰写回答