3

我想在 python 中构建一个循环文件​​缓冲区来保存文件名(字符串)。缓冲区应具有以下属性。

  • 缓冲区的大小是其名称存储在缓冲区中的文件大小的总和。缓冲区将具有最大允许大小。
  • 添加新文件时,如果缓冲区大小小于最大允许大小,则添加该文件名字符串。否则,最旧的修改文件将被推出并添加新文件。如果新添加的文件比缓冲区中已经存在的所有文件都旧,则不会发生任何事情。

是否可以为此目的扩展双端队列?

还是我应该从头开始写?有没有我可以用于此目的的设计理念?

谢谢

肯定的

4

2 回答 2

4

好的,我相信 Raymond Hettinger 对您的问题的解释是正确的,并且您的评论已经澄清您不关心队列的长度,而是关心所有文件大小的总和。这更有意义,我很高兴我终于明白你的意思了。考虑到这一点,这里有一个简单的实现heapq,我相信它可以满足您提出的所有要求。通过putting(timestamp, filename, filesize)队列上的元组来使用它,并注意当您get从队列中取出一个项目时,它将是最旧的文件(即具有最小时间戳的文件。)

import heapq

class FilenameQueue(object):
    def __init__(self, times_sizes_names, maxsize):
        self.maxsize = maxsize
        self.size = sum(s for t, s, n in times_sizes_names)
        self.files = list(times_sizes_names)
        heapq.heapify(self.files)
        while self.size > self.maxsize:
            self.get()
    def __len__(self):
        return len(self.files)
    def put(self, time_size_name):
        self.size += time_size_name[1]
        if self.size < self.maxsize:
            heapq.heappush(self.files, time_size_name)
        else:
            time_size_name = heapq.heappushpop(self.files, time_size_name)
            self.size -= time_size_name[1]
    def get(self):
        time_size_name = heapq.heappop(self.files)
        self.size -= time_size_name[1]
        return time_size_name

我添加了一个__len__方法,以便您可以在获取队列之前对其进行测试。这是一个使用示例:

>>> f = FilenameQueue(((22, 33, 'f1'), (44, 55, 'f2'), (33, 22, 'f3')), 150)
>>> while f:
...     f.get()
... 
(22, 33, 'f1')
(33, 22, 'f3')
(44, 55, 'f2')
>>> f = FilenameQueue(((22, 33, 'f1'), (44, 55, 'f2'), (33, 22, 'f3')), 150)
>>> f.put((55, 66, 'f4'))
>>> while f:
...     f.get()
... 
(33, 22, 'f3')
(44, 55, 'f2')
(55, 66, 'f4')

请参阅我的编辑历史记录,以了解涉及Queue.PriorityQueue次优的完全不同的解决方案。我忘记了通过阻止而不是通过丢弃元素来maxsize强制限制。那不是很有用!

于 2012-04-16T02:19:32.710 回答
3

如果我正确阅读了您的问题,则您需要一系列文件名,文件名不超过给定的最大大小。如果添加的新文件超过了最大值,您希望忘记最旧的文件。

这个简单的基于双端队列的类应该很好地处理它:

from collections import deque

class FileDeque(object):
    'FIFO queue of files upto a given total size'

    def __init__(self, maxsize):
        self.maxsize = maxsize
        self.d = deque()
        self.sizes = dict()
        self.currsize = 0

    def append(self, filename, filesize):
        'Add a new file to the FileDeque'
        self.d.append(filename)
        self.sizes[filename] = filesize
        self.currsize += filesize
        while self.currsize > self.maxsize and self.d:
            oldfilename = self.d.popleft()
            oldfilesize = self.sizes.pop(oldfilename)
            self.currsize -= oldfilesize

    def __iter__(self):
        'List files oldest to newest'
        return iter(self.d)

示例会话如下所示:

>>> f = FileDeque(maxsize=10000)
>>> f.append('raptors.txt', 2500)
>>> f.append('rexes.txt', 4200)
>>> list(f)
['raptors.txt', 'rexes.txt']
>>> f.append('stegos.txt', 5000)
>>> list(f)
['rexes.txt', 'stegos.txt']
>>> f.append('brontos.txt', 500)
>>> list(f)
['rexes.txt', 'stegos.txt', 'brontos.txt']
>>> f.append('dactyls.txt', 4000)
>>> list(f)
['stegos.txt', 'brontos.txt', 'dactyls.txt']
于 2012-04-16T02:53:08.457 回答