【问题标题】:examining items in a python Queue检查 python 队列中的项目
【发布时间】:2013-05-17 04:21:37
【问题描述】:

是否可以在不调用 .get() 的情况下在 Python 中检查 Queue 中的项目?根据文档,队列中不允许索引。我需要检查队列头部的项目是否满足某些条件,如果满足,请将其从队列中删除。同样,我需要检查队列中的任何其他项目是否满足类似条件并将其删除。

我在这里使用了错误的数据结构吗?

【问题讨论】:

  • 听起来你应该改用collections.deque,你在用线程吗?
  • 不,我没有使用线程

标签: python queue


【解决方案1】:

简单地访问底层队列并不安全。

安全的方法是扩展 Queue 类。如果您返回底层 dequeue 对象,您将不会获得副本,您会获得活动对象

这样做的结果是它可以在您迭代它时发生变化 - 如果在您的迭代期间另一个线程插入到队列中,这将导致异常。

知道python使用GIL,你可以放心地使用list(q.queue),因为list()永远不会引起上下文切换。

最好使用与 get() 函数相同的锁,不要对 GIL 做任何假设:

import queue
    
class SnapshotQueue(queue.Queue):
    def snapshot(self):
        with self.mutex
            return list(self.queue)

可以安全地使用该类而不是常规队列,并且它将返回队列状态的快照...在互斥锁中并且不会导致底层队列操作出现问题。

【讨论】:

  • nit:您在 with 行缺少冒号。但这是一个很好的答案。
【解决方案2】:

Queue 模块实现了多生产者、多消费者队列。当必须在多个线程之间安全地交换信息时,它在线程编程中特别有用。

如您所见,Queue 模块是专门为与线程一起使用而创建的,仅提供 FIFOLIFO优先队列 ,其中没有一个提供此功能。然而,通过检查Queue 模块的source code,您可以看到它只是使用了一个collections.deque(双端队列),可以轻松完成您的任务。您可以在恒定时间内索引第一项([0])和.popleft()

【讨论】:

  • 为了避免误解,也许你应该(对于其他读者)提到Queue 有一个self.mutex = _threading.Lock(),但不是deques,所以在多线程环境中使用后者而不是前者是不等价的——这里不是这种情况,因为 OP 提到线程没有被用作评论。
【解决方案3】:

queue_object.queue 将在一个双端队列对象中返回您的队列副本,然后您可以使用它的切片。当然,它不会与原始队列同步,但可以让您在复制时查看队列。

在此线程comp.lang.python - Queue peek? 中详细解释了您不想这样做的原因有一个很好的合理化解释。但如果您只是想了解 Queue 的工作原理,这是一种简单的方法。

import Queue
q = Queue.Queue()
q.push(1)
q.put('foo')
q.put('bar')
d = q.queue
print(d)
deque(['foo', 'bar'])
print(d[0])
'foo'

【讨论】:

  • 而你 -1 一个我,因为我正确回答了他的问题? ..这真的很粗鲁。您没有考虑到他可能正在使用需要队列互斥锁的现有代码,而他只是试图了解它是如何工作的——完全观察队列。忽略这个问题(这是一个合理的新手问题),或者 -1 我的正确答案与 stackoverflow 的精神和试图帮助人们的精神背道而驰。
  • -1d 因为你没有正确回答它,你也没有提到如何删除它,这也是这项工作的错误任务(OP 不需要队列互斥锁如 cmets 中所述)
  • 问题是:'是否可以在不调用 get() 的情况下在 python 中检查队列中的项目?'。是的。它是。我解释了如何。对于 OP 来说,他可以切换到双端队列很棒,其他拥有已建立代码库的人可能无法做到。
  • 虽然Queue 对象的.queue 属性没有前导_ 表明它是私有的,但它没有记录,所以我不愿意使用它。我不会对你的回答投反对票,但我认为这不是一个好建议。
  • @jamylak 你说得对。 stackoverflow 有一个严重的问题,不清楚答案应该是迂腐的(“你的问题意味着你做错了什么”)还是务实的(“这是你要求做的不安全的事情”)。正确的建议是:两者都做。 1. 给出不安全的方法和 2. 解释为什么不应该使用它。回答问题时,您不知道为什么有人问他们。
猜你喜欢
  • 2012-09-23
  • 2018-07-07
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
相关资源
最近更新 更多