2017-07-03 87 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来说,它确实是例外。他的“生活”围绕着处理数据而建立,但他们对他来说没有任何工作,甚至没有睡眠任务