繁体   English   中英

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

[英]How to iterate through a Python Queue.Queue with a for loop instead of a while loop?

通常我们这样编码:

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

您可以将iter与 callable 一起使用。 (您应该传递两个参数,一个用于可调用对象,另一个用于标记值)

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 job in iter(queue.get, None):

表现与

while True:
  data = queue.get()
  if data is None:
    break

如果有多个进程在起作用。 我没有可复制的示例,但是前者比后者早结束了。 我认为这可能与订购和东西有关,但不知道,真的...

如果进程A通过从文件中读取行并进行转换来填充队列。 而且流程B正在从该队列中消耗资源,我想到在第一个实现中,流程B在例如6个项目之后结束,即使我知道流程A处理了10个项目,然后将哨兵None放入队列中。

我想这是更简单的方法

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM