为什么Python的queue.Queue.get()允许从超时中提前返回?

时间:2011-06-07 06:15:11

标签: python real-time

更新:这个问题是基于Queue.get()实际行为的错误心智模型,这是由一些略微模糊的文档引起的,但主要是由timedelta.total_seconds()的错误的手动实现引起的。当我试图证明原始答案不正确时,我发现了这个错误。现在timedelta.total_seconds()由Python提供(自2.7起),我将继续使用它。

很抱歉这个混乱。


这不是“我的代码为什么不运行?”问题,但“这个设计决定背后的动机是什么?”

从2.3开始,Python的队列模块包含一个带有get方法的Queue类,它接受一个超时参数。以下是手册中的部分:

Queue.get([block[, timeout]])
从队列中删除并返回一个项目。如果可选的args块为true且timeout为None(默认值),则在必要时阻止,直到某个项可用为止。如果超时为正数,则会阻止 最多 超时秒,如果在该时间内没有项目可用,则会引发Empty异常。 [...]

(强调我的)

请注意,即使尚未达到超时,它也可能引发空异常。事实上,我在Ubuntu(但不是Windows)上看到了这种行为。它只是提前退出,它对我的​​代码产生了轻微的影响 - 我可以编写代码。

大多数阻止超时需要最小超时,这在非实时操作系统(包括Windows和Linux)上是有意义的。无法保证操作系统在任何给定的截止日期之前将上下文切换到您的进程或线程。

但是,这个会占用最大超时。任何人都可以解释这个设计决定可能有意义吗?

3 个答案:

答案 0 :(得分:5)

我认为你误解了文档。并不是说它可能会在不到Empty秒之后引发timeout异常,它说它最多会阻塞timeout秒。如果它可以满足get

,它可能会阻止少于此

我意识到你说你看到它提前Empty提升,但说实话,这听起来像是一个错误,或者说你依赖的系统比系统提供的更准确。 (看起来似乎要遵守规范的确切措辞,实现应该将timeout 分解为其计时器的分辨率,而不是像您希望的那样向上。)< / p>

答案 1 :(得分:4)

除非你正在进行实时编程,否则正确的程序必须假设任何超时值都是一个指导,所以你错误的哪一方都无关紧要。请注意,如果队列保持为空,queue 等待至少超时(通过查看代码确认,如果{基本上是退出的循环{1}}(时间)小于0)。但是,如果在此期间将项目放入队列,它会更早返回。

您期待这种行为:

remaining

但有效的时间表也是如此:

[0] (Thread) A calls Queue.get(True, 10)
[0] B waits 9 seconds
[9] B does something on X
[11] A destroys X

你需要修改程序才能独立于当时选择线程的实际时间。

答案 2 :(得分:0)

Queue.get 中肯定存在一个错误,至少在python 2.6.6中是这样。 在posix上, queue.get(timeout = 1)似乎几乎立即退出(引发Empty异常),而 queue.get(timeout = 2)工作正常。

我使用的是一个并发线程的队列* get * on ... ...