[英]How to make Python's multiprocessing Queue's .empty() method return the correct value? Or alternatives?
我有這個片段,它使用multiprocess
模塊中的Queue
類。 我很困惑Queue
實例的.empty()
方法沒有像我期望的那樣給我一個正確的值。 這是我的代碼:
from time import sleep
from multiprocessing import Queue, Lock
foo = Queue()
locker = Lock()
with locker: # even with this, still True
foo.put("bar")
print(foo.empty()) # True, obviously not
print(foo.empty()) # True
print(foo.empty()) # True
print(foo.qsize()) # 1L
print(foo.empty()) # True
但是,如果我從time
使用sleep
函數,則會導致執行中按時間順序延遲。 有用。
from time import sleep
from multiprocessing import Queue, Lock
foo = Queue()
locker = Lock()
foo.put("bar")
sleep(0.01)
print(foo.empty()) # False
print(foo.empty()) # False
print(foo.empty()) # False
print(foo.qsize()) # 1L
print(foo.empty()) # False
我知道我的替代方案是.qsize() > 0
表達式,但我確信我只是以錯誤的方式這樣做。
我究竟做錯了什么?
*編輯*
我現在明白這是不可靠的,謝謝@Mathias Ettinger。 任何干凈的替代品? 我需要知道 hot 才能可靠地判斷我的Queue
是否為空。
不幸的是,隊列的復雜實現意味着.empty()
和.qsize()
檢查不同的東西來做出判斷。 這意味着他們可能會暫時不同意,正如您所見。
由於.qsize()
支持您的平台上(這是不是真的無處不在),你可以重新實現.empty()
來講檢查.qsize()
這會為你工作:
# mp.Queue() is a function, not a class, so we need to find the true class
# to subclass
import multiprocessing.queues
class XQueue(multiprocessing.queues.Queue):
def empty(self):
try:
return self.qsize() == 0
except NotImplementedError: # OS X -- see qsize() implementation
return super(XQueue, self).empty()
在.put()
,Queue .put()
是一個復雜的過程:Queue 將對象放入緩沖區並獲取進程間信號量,而隱藏的守護線程負責排空緩沖區並將其內容序列化到管道。 (消費者然后.get()
通過從此管道讀取並釋放進程間信號量。)所以,這就是為什么在您的示例中休眠的原因:守護線程有足夠的時間將對象從內存緩沖區移動到 I/O 表示之前你打電話給.empty()
。
順便說一句,我發現這種行為令人驚訝:處於相同內部狀態的隊列可以對“您有任何元素入隊嗎?”這個問題給出兩種不同的答案。 ( qsize
會說“是”,而empty
“否”。)
我想我明白這是怎么回事了。 由於並非所有平台都支持sem_getvalue()
,因此並非所有平台都可以實現qsize
,但只需輪詢 FIFO 即可合理實現empty
。 我曾期望在支持后者的平台上根據qsize
實現empty
。
根據文檔, empty()
、 full()
和qsize()
都不可靠。
替代方案包括:
讀取通過Queue
的確切項目數量:
AMT = 8 for _ in range(AMT): queue.put('some stuff') for _ in range(AMT): print(queue.get())
如果您事先知道總共必須處理多少項或每個線程將處理多少項,這將非常有用。
閱讀項目直到監護人出現:
num_threads = 8 guardian = 'STUFF DONE' while num_threads: item = queue.get() if item == guardian: num_threads -= 1 else: process(item)
如果每個線程都有可變數量的工作(並且您事先不知道總數)要做但可以確定何時完成,這將很有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.