簡體   English   中英

如何讓 Python 的多處理隊列的 .empty() 方法返回正確的值? 或者替代品?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM