2017-07-03 101 views
0

我有一個生產者和許多消費者的應用程序和一個隊列,溝通他們。 消費者應該從隊列中收集一些數據,比如qsize()/number_of_consumers,但當出現sentinel時,它必須停止工作。for循環發生器與哨兵

我有這樣的代碼:

frame = 0 
elems_max = 10 
while frame is not None: 
    frames = [] 
    for _ in range(elems_max): 
     frame = queue_in.get() 
     if frame: 
      frames.append(frame) 
     else: 
      break 
    process_data(frames) 

,你可以看到None是這個隊列中的哨兵,而當它出現時我wan't打破我的工作過程。我也想獲取更多的數據處理元素。

什麼是最快的方法來實現這[在python 3.5]?

+0

你是什麼意思「我想打破我的工作過程」?你的意思是你的'while'循環嗎? –

+0

是的,我不想打破我的和while循環。 –

回答

2

我知道你在遇到None時想破壞你的外部while

您可以容納一個布爾變量,即True,而while必須執行,而False應該停止。

這應該是這樣的:

frame = 0 
elems_max = 10 
running = True 
while running and frame is not None: 
    frames = [] 
    for _ in range(elems_max): 
     frame = queue_in.get() 
     if frame is not None: 
      frames.append(frame) 
     else: 
      running = False 
      break 
    process_data(frames) 

break指令將打破內for,而不是外while。 但是,將running設置爲False後,while循環將停止。


根據您的評論。

這是不可能包括在修真break聲明,也不是else條款,如您想做的事:

幀= [f有關我在範圍內,如果queue_in.get()是(elems_max)不無其他休息]

但是,您可以建立您的清單,然後經過刪除所有元素的None

frames = [queue_in.get() for _ in range(elems_max)] 

try: 
    noneId = frames.find(None) 
    frames = frames[:noneId] 
except ValueError: 
    pass 

這是不是很有效,因爲許多潛在的因素將在0123追加沒有。 我寧願手動施工,以避免這種危害。


另一個解決方案,基於一個發電機。 這可能不是您所期望的,但語法很簡單,所以您可能會喜歡它。

的想法是包裹發電機內部的數據的獲得,是對None值突破:

def queue_data_generator(queue, count): 
    for _ in range(count): 
     item = queue.get() 
     if item is None: 
      raise StopIteration 
     else: 
      yield item 

然後,實例化這個發電機,並簡單地遍歷它:

g = queue_data_generator(queue_in, elems_max) 
frames = [frame for frame in g] 

frames列表將包含queue_in中包含的所有幀,直到第一個None。 這個用法很簡單,但你必須通過定義生成器來設置它。 雖然我覺得它很優雅。

+0

這不是我的問題的目的,我的代碼while循環中斷。如果有這個代碼的話,我不是最快的方法嗎? –

+0

@GrzegorzGłowacki嗯,我不知道你在用什麼Python,但'break'絕對不會破壞'while':正如[文檔]中所述(https://docs.python.org/2 /tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops),「break語句,就像在C中,打破了最內層的for或while循環。」無論如何,「最快的方法」是什麼意思?如果你想要最短的代碼,那麼把'while'放在'try'塊內可能是最短的,儘管它需要你改變你的'process_data'函數,以便引發一個異常。 –

+0

break不會中斷while循環,但frame被設置爲None,並且它會停止循環執行 –

0

我會做下一個(有點僞代碼):

class CInputQueue: 
    def get(self, preffered_N): 
     # do sync stuff 
     # take <= N elements (you can do kinda balance the load) 
     # or throw exception 
     raise Exception("No data, no work, no life.") 

elems_max = 10 
try: 
    while True: 
     process_data(queue_in.get(elems_max)) 
except: 
    None # break 

我認爲數據處理需要更多的時間,比0毫秒,所以我使用異常。我知道這不是用於流量控制的okey使用例外,但對於worker來說,它確實是例外。他的「生活」圍繞着處理數據而建立,但他們對他來說沒有任何工作,甚至沒有睡眠任務