【问题标题】:Clear all items from the queue清除队列中的所有项目
【发布时间】:2011-09-24 23:12:48
【问题描述】:

如何清除队列。例如我在队列中有数据,但由于某种原因我不需要现有数据,只想清空队列。

有什么办法吗?这行得通吗:

oldQueue = Queue.Queue()

【问题讨论】:

  • 如果您阅读文档,它会将您引向 Queue 模块的 latest source,在那里您可以看到 FIFO 队列的内部表示是 deque。在deque 的文档中,您会注意到它有一个clear() 方法,这就是您想要的。您可能还想用 q.mutex.acquire()q.mutex.release() 包装该调用,因为其余代码围绕此类操作执行以使其线程安全。

标签: python queue


【解决方案1】:
q = Queue.Queue()
q.queue.clear()

编辑 为了清晰和简洁,我省略了线程安全的问题,但@Dan D 非常正确,以下更好。

q = Queue.Queue()
with q.mutex:
    q.queue.clear()

【讨论】:

  • 如果你做with q.mutex: q.queue.clear(),这个操作将是线程安全的。
  • @DanD。如果我错了,请纠正我,但这对我来说实际上是一个的想法。 .mutex.queue seems to be undocumented 如果我没记错的话,使用 q.mutex死锁,如果你在它的块内做任何类似q.get_nowait 的事情。
  • n611x007 和 user2357112 是正确的。我希望在无证/私人成员之前有一个下划线,误导我相信 clear() 在安全的 API 中。无论如何,清除队列似乎是个坏主意,最好阅读它并丢弃不需要的项目。
  • 请注意,如下文 V.E.O 的回答所述,仅清除是不够的,因为即使队列为空,相应的任务也没有被标记为已完成。这可能会导致您的代码被锁定。
  • 我也使用了下面的方法,使用 q.mutex: size = len(q.queue) q.queue.clear() q.unfinished_tasks -= size 为 join( ) 阻止
【解决方案2】:

你只是不能清除队列,因为每个 put 还添加了 unfinished_tasks 成员。 连接方法取决于此值。 并且 all_tasks_done 也需要得到通知。

q.mutex.acquire()
q.queue.clear()
q.all_tasks_done.notify_all()
q.unfinished_tasks = 0
q.mutex.release()

或者以体面的方式,使用 get 和 task_done 对来安全地清除任务。

while not q.empty():
    try:
        q.get(False)
    except Empty:
        continue
    q.task_done()

或者只是创建一个新队列并删除旧队列。

【讨论】:

  • 使用该方法也要小心。 docs 注释,“如果 empty() 返回 False,则不能保证后续对 get() 的调用不会阻塞。”
  • @Lack 是的,通过非阻塞get修复它
  • 第二种方式(“体面”的方式)似乎是最安全、更优雅的方式,并且仅使用文档化的公共 API。谁能确认一下?
  • 似乎这些在并发看跌期权上的行为会略有不同。第一个将阻塞并发 put,而第二个将在下一个循环中捕获并删除并发 put。对吗?
  • 体面的方式并不能保证它会完全结束。更不用说循环开销了。我会坚持第一种方式。
【解决方案3】:

这对我来说似乎做得很好。我欢迎 cmets/additions 以防我错过任何重要的事情。

class Queue(queue.Queue):
  '''
  A custom queue subclass that provides a :meth:`clear` method.
  '''

  def clear(self):
    '''
    Clears all items from the queue.
    '''

    with self.mutex:
      unfinished = self.unfinished_tasks - len(self.queue)
      if unfinished <= 0:
        if unfinished < 0:
          raise ValueError('task_done() called too many times')
        self.all_tasks_done.notify_all()
      self.unfinished_tasks = unfinished
      self.queue.clear()
      self.not_full.notify_all()

【讨论】:

  • 这似乎是最有效(致电.clear())和正确(包括当前处理的项目的通知)的方法。
  • 多处理实现会像这样吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多