2011-06-07 17 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)工作正常。

我使用與併發線程的單個隊列* 獲得荷蘭國際集團 *就可以了...

相關問題