我有一个我在循环中处理的队列
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
个元素”。我在文档中找不到类似的东西。 有没有办法从队列中一次弹出多个元素(例如切片列表)?
答案 0 :(得分:1)
Queue.get
块;无限循环的来源。
Queue.get(block=True, timeout=None)
从队列中删除并返回一个项目。 如果是可选的args块 true和timeout是None(默认值),必要时阻止直到 item是可用的。如果timeout是一个正数,它最多会阻塞 超时秒,如果没有项,则引发Empty异常 在那段时间内可用。否则(块为假),返回一个项目 如果一个立即可用,否则引发Empty异常 (在这种情况下会忽略超时)。
您应该使用Queue.get_nowait
或Queue.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次无用的尝试来获取一个元素(队列为空),或者拥有所有这些(即使队列增长),或者介于两者之间的任何东西