如果您需要一个能够在达到最大容量时自动丢弃项目的先入先出(FIFO)队列,那么您将需要一个自动丢弃的FIFO队列。这种队列不一定是线程安全的,效率更重要。
例如,您需要从设备中采样信号,同时能够在半随机时间检索最后n秒(对象)。您可以实现一个(不太线程安全)的缓冲区,但您可能会觉得您在重复发明轮子。此外,我们正在谈论每秒100个对象。大多数将被丢弃,而3000(= 30秒的数据)将一次被检索(例如,每十分一次)。那么,在Python标准库或其他地方是否已经存在这样的类呢?
2、解决方案 您可以使用Queue模块来实现一个自动丢弃的FIFO队列。Queue模块提供了一个简单的FIFO队列实现,您可以通过指定maxsize参数来限制队列的最大容量。当队列已满时,您尝试将新项目添加到队列时,队列将自动丢弃最旧的项目。
以下是一个自动丢弃的FIFO队列的示例实现:
from Queue import Queue, Full, Empty
import logging
class DiscardingBuffer():
def __init__(self, capacity=0):
self._queue = Queue(maxsize=capacity)
def put(self, item):
while True:
try:
self._queue.put(item, block=False)
logging.debug('Put item: {0}'.format(item))
break
except Full:
discarded_item = self._queue.get(block=False)
logging.debug('Buffer is full. Discarding: {0}'.format(discarded_item))
def flush(self):
items = []
while True:
try:
items.append(self._queue.get(block=False))
except Empty:
logging.debug('Buffer is now empty.')
break
return items
def main():
buf = DiscardingBuffer(5)
for i in xrange(10):
buf.put(i)
logging.debug('Remaining items: {0}'.format(buf.flush()))
logging.debug('Verify it is empty: {0}'.format(buf.flush()))
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG,
format='[%(levelname)1.1s %(asctime)s %(name)s (%(process)d):%(lineno)d] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
main()
这个脚本创建了一个DiscardingBuffer对象,并用数字0到9填充它。然后它调用flush()方法来获取剩余项目并清空缓冲区。最后,它再次调用flush()方法来确保缓冲区已清空。
输出:
[D 2013-08-22 10:13:58 root (4164):13] Put item: 0
[D 2013-08-22 10:13:58 root (4164):13] Put item: 1
[D 2013-08-22 10:13:58 root (4164):13] Put item: 2
[D 2013-08-22 10:13:58 root (4164):13] Put item: 3
[D 2013-08-22 10:13:58 root (4164):13] Put item: 4
[D 2013-08-22 10:13:58 root (4164):17] Buffer is full. Discarding: 0
[D 2013-08-22 10:13:58 root (4164):13] Put item: 5
[D 2013-08-22 10:13:58 root (4164):17] Buffer is full. Discarding: 1
[D 2013-08-22 10:13:58 root (4164):13] Put item: 6
[D 2013-08-22 10:13:58 root (4164):17] Buffer is full. Discarding: 2
[D 2013-08-22 10:13:58 root (4164):13] Put item: 7
[D 2013-08-22 10:13:58 root (4164):17] Buffer is full. Discarding: 3
[D 2013-08-22 10:13:58 root (4164):13] Put item: 8
[D 2013-08-22 10:13:58 root (4164):17] Buffer is full. Discarding: 4
[D 2013-08-22 10:13:58 root (4164):13] Put item: 9
[D 2013-08-22 10:13:58 root (4164):26] Buffer is now empty.
[D 2013-08-22 10:13:58 root (4164):38] Remaining items: [5, 6, 7, 8, 9]
[D 2013-08-22 10:13:58 root (4164):26] Buffer is now empty.
[D 2013-08-22 10:13:58 root (4164):39] Verify it is empty: []
您还可以使用collections.deque指定一个maxlen,来实现一个自动丢弃的FIFO队列:
>>> q = deque(maxlen=2)
>>> q.extend([1, 2, 3])
>>> q
deque([2, 3], maxlen=2)
希望这可以帮助您实现您需要的自动丢弃的FIFO队列。