2011-06-07 92 views
4

更新:这个问题是基于Queue.get()的实际行为方式的错误思维模型,这是由一些稍微模糊的文档引起的,但主要是由一个错误的手动实现timedelta.total_seconds()引起的。当我试图证明原始答案不正确时,我发现了这个错误。现在Python已经提供了timedelta.total_seconds()(从2.7开始),我将转而使用它。为什么Python的queue.Queue.get()允许从超时提前返回?

对不起,我感到困惑。


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

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

Queue.get([block[, timeout]])
从队列中移除并返回一个项目。如果可选参数块为true并且超时时间为无(默认值),则在必要时阻止,直到项目可用。如果超时时间为正数,则会阻止 至多超时秒数,如果在该时间内没有可用项目,则会引发空例外。 [...]

(重点煤矿)

注意,这可能会引发空异常即使它没有达到超时。事实上,我在Ubuntu上看到了这种行为(但不是Windows)。它只是提前一点退出,它对我的​​代码有轻微的影响 - 尽管如此,我仍然可以对它进行编码。

大多数阻塞超时最少需要超时,这对非实时OS(包括Windows和Linux)有意义。不能保证操作系统会在任何给定的最后期限内切换到您的进程或线程。

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

回答

5

我认为你错误地解释了文档。这并不是说它可能会在小于timeout秒之后提高Empty例外,而是说它将阻止最多timeout秒。如果它可以满足get,它可能会阻止低于此值。

我意识到你在说早些时候看到它会提高Empty,但说实话,这听起来像是一个错误,或者说你依赖的系统可以提供更高的准确性。 (它似乎,好像,服从规范的确切措辞,实现应该timeout舍入到其计时器的分辨率,而不是了,你似乎渴望。)

4

除非您正在进行实时编程,否则正确的程序必须假定任何超时值都是指导,因此无论您在哪个方面出错都无关紧要。请注意,queue确实等待至少超时如果队列保持为空(通过代码中的查找确认,基本上是一个循环,如果remaining(时间)小于0则退出)。尽管如此,如果一个项目同时被放入队列中,它会返回更早。

你希望此行为:

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

但是一个有效的计划是和:

[0] (Thread) A calls Queue.get(True, 10) 
[0] B waits 9 seconds 
[9] Operating system is busy for 2 seconds 
[11] A gets picked by the OS, destroys X  
[12] B does something on X 

您需要修复程序独立工作的实际时间的哪个线程的被选中时。

+0

+1检查背后Queue.Queue的代码。这震动了我对我的立场的信心。我本应该这样做。然而,虽然我很困惑,但这并不是我遇到的困惑。我声称线程A在队列中没有任何东西在[9.999]醒来。由于执行错误,我现在看到我正在睡9.999而不是10。 – Oddthinking 2011-06-07 11:29:09

0

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

我使用与并发线程的单个队列* 获得荷兰国际集团 *就可以了...

相关问题