如何切片队列?

时间:2018-03-08 11:47:12

标签: python python-3.x queue

我有一个我在循环中处理的队列

while True:
    # a processing loop
    batch = []
    while True:
        e = q.get()
        if e:
            batch.append(e)
        else:
            # the queue is empty
            break
    do_something_with(batch)
    # wait a moment before emptying the queue again
    time.sleep(2)

我们的想法是清空队列,处理其内容并等待一会儿再次检查内容。

我有时会遇到一个竞争条件,其中队列是get()一个元素,并且我最终会增加batch,而这种情况永远不会被进一步处理。

一种解决方案是检查batch大小并在大小合适时处理它。如果我没有那么多事件进入队列并且batch永远不会达到正确的大小 - 这就不起作用了 - 但是我需要处理事件(无论它们的数量是什么),而不是等到有足够的事件累积。

第二种解决方案是根据大小和batch空闲时间构建检查 - 这使代码过于复杂。

一个好的解决方案是“立即从队列中获取n个元素”。我在文档中找不到类似的东西。 有没有办法从队列中一次弹出多个元素(例如切片列表)?

2 个答案:

答案 0 :(得分:1)

默认情况下

Queue.get块;无限循环的来源。

  

Queue.get(block=True, timeout=None)

     

从队列中删除并返回一个项目。 如果是可选的args块   true和timeout是None(默认值),必要时阻止直到   item是可用的。如果timeout是一个正数,它最多会阻塞   超时秒,如果没有项,则引发Empty异常   在那段时间内可用。否则(块为假),返回一个项目   如果一个立即可用,否则引发Empty异常   (在这种情况下会忽略超时)。

您应该使用Queue.get_nowaitQueue.get(block=False)来阻止阻止。或者当队列为空时,使用Queue.get(timeout=<seconds>)最多等待<seconds>

你问题中提到的解决方案听起来不错:

BATCH_SIZE = 10

while True:
    batch = []

    # Get out of loop if enough item collected or queue is empty
    while len(batch) < BATCH_SIZE:
        try:
            e = q.get_nowait()  # OR q.get(timeout=0.1)
        except Empty:
            break
            # To prevent empty batch
            # if batch:
            #     break

    do_something_with(batch)
    # wait a moment before emptying the queue again
    time.sleep(2)

答案 1 :(得分:0)

我现在正在使用的解决方法,直到更好的想法/解决方案:

while True:
    # get up to 1000 elements form the queue
    batch = []
    for _ in range(1000):
        try:
            e = q.get(block=False)
        except queue.Empty:
            continue
        else:
            batch.append(e)
    do_something_with(batch)
    time.sleep(2)

我可能会做出1000次无用的尝试来获取一个元素(队列为空),或者拥有所有这些(即使队列增长),或者介于两者之间的任何东西