为什么Python';s queue.queue.get()是否允许从超时中提前返回?

为什么Python';s queue.queue.get()是否允许从超时中提前返回?,python,real-time,Python,Real Time,更新:这个问题基于Queue.get()实际行为的错误心理模型,这是由一些稍微模棱两可的文档引起的,但主要是由timedelta.total_seconds()的错误手动实现引起的。我在试图证明原始答案不正确时发现了这个错误。既然Python提供了timedelta.total_seconds()(从2.7开始),我将使用它 很抱歉给你带来了困惑 这不是一个“为什么我的代码没有运行?”的问题,而是一个“这个设计决策背后的动机是什么?” 从2.3开始,Python的队列模块包含一个带有get方法

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

很抱歉给你带来了困惑


这不是一个“为什么我的代码没有运行?”的问题,而是一个“这个设计决策背后的动机是什么?”

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

Queue.get([block[,timeout]])

从队列中删除并返回项目。如果optional args block为true,timeout为None(默认值),则根据需要进行阻塞,直到某个项可用。如果timeout为正数,则它最多会阻止超时秒,如果在此时间内没有可用项,则引发空异常。[...] (强调矿山)

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

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


但是,此操作需要最大超时时间。有人能解释一下这个设计决策有什么意义吗?

除非您正在进行实时编程,否则正确的程序必须假定任何超时值都是一个指导,所以无论您在哪方面出错都无关紧要。请注意,
队列
如果队列保持为空(通过查看代码确认,该代码基本上是一个循环,如果剩余的(时间)小于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

您需要修复程序,使其独立于何时选择线程的实际计时工作。

我认为您误解了文档。它并不是说它可能在
超时
秒以下引发
异常,而是说它最多会阻塞
超时
秒。如果它能够满足
get
,它可能会阻塞小于该值


我知道你是说你看到它很早就出现了
Empty
,但老实说,这听起来像是一个bug,或者你依赖的是比系统所能提供的更高的准确性。(看起来,为了遵守规范的确切措辞,实现应该将
timeout
四舍五入到计时器的分辨率,而不是像您希望的那样向上。)

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


我使用了一个带有并发线程的单队列来检查queue.queue后面的代码…

+1。这动摇了我对自己地位的信心。我应该自己做的。然而,虽然我很困惑,但这并不是我现在的困惑。我声称线程A在[9.999]醒来时没有任何东西在队列中。我现在看到,由于一个实现错误,我睡了9.999而不是10分钟。