如何遍历 Python Queue.Queue 使用 for 循环而不是 while 循环



通常我们这样编码:

while True:
    job = queue.get()
    ...

但是,是否有可能做一些事情:

for job in queue.get():
    #do stuff to job

我想这样做的真正原因是因为我想使用 python-progressbar 的自动检测 maxval。他们这样做就像for this in progressbar(that):

您可以将

iter与可调用一起使用。(您应该传递两个参数,一个用于可调用对象,另一个用于哨兵值)

for job in iter(queue.get, None): # Replace `None` as you need.
    # do stuff with job

注意 当没有元素保留且没有放置哨兵值时,这将阻止。此外,与 while - get 循环不同,与容器上的正常for循环不同,它将从队列中删除项目。

None是通用值,因此下面是一个具有更具体哨兵值的示例:

sentinel = object()
for job in iter(queue.get, sentinel):
    # do stuff with job
我会

说这是一种在某些点上迭代队列的简单方法:

from queue import Queue
q = Queue()
q.put(1)
q.put(2)
q.put(3)
for i in q.queue:
    print(i)

对于这种队列,实际上我通常不会使用这种queue.empty()检查,因为我总是在线程上下文中使用它,因此无法知道另一个线程是否会在几毫秒内将某些东西放在那里(因此该检查无论如何都是无用的)。 我从不检查队列是否为空。 我宁愿使用一个哨兵值来标记生产者的结局。

所以使用iter(queue.get, Sentinel)是我喜欢的。

如果您知道没有其他线程将项目再放入队列中,并且只想从所有当前包含的项目中排出它,那么您可以像这样使用 sth:

class Drainer(object):
  def __init__(self, q):
    self.q = q
  def __iter__(self):
    while True:
      try:
        yield self.q.get_nowait()
      except queue.Empty:  # on python 2 use Queue.Empty
        break
for item in Drainer(q):
  print(item)

def drain(q):
  while True:
    try:
      yield q.get_nowait()
    except queue.Empty:  # on python 2 use Queue.Empty
      break
for item in drain(q):
  print(item)

我的第一个是iter函数,但是内置的队列模块不返回哨兵,所以一个不错的选择可能是定义自己的包装类:

import Queue
class IterableQueue():
    def __init__(self,source_queue):
            self.source_queue = source_queue
    def __iter__(self):
        while True:
            try:
               yield self.source_queue.get_nowait()
            except Queue.Empty:
               return

这个迭代器包装队列并生成,直到队列为空,然后返回,所以现在你可以这样做:

q = Queue.Queue()
q.put(1)
q.put(2)
q.put(3)
for n in IterableQueue(q):
    print(n)

输出:

1
2
3

这种方法有点冗长,如果有人知道使用内置的东西更好,那会很有趣。

我想这是更简单的方法

for elem in list(q.queue):
      print(elem)

最新更新