可以从functools.lru_cache中替换或删除特定键吗?

时间:2018-07-24 17:35:38

标签: python python-3.x caching lru functools

在给定某些输入 * 的情况下,我使用functools.lru_cache来提供临时文件路径。但是,如果路径不再存在,我想删除/替换单个对应的密钥。 cache_clear()方法可能会过大,cache_info()似乎无济于事。

感谢您的帮助!

* 正在缓存的方法将fileobj从S3流传输到本地临时文件。

3 个答案:

答案 0 :(得分:1)

这是通过python.org问题allow to cache_clear(some_key) in lru_cache提出的,遭到拒绝。因此,lru_cache中没有清除特定条目的方法。

与该问题相关的一个很好的建议是使用名为Foundation for rolling your own LRU cache variantscollections.OrderedDict实现您自己的变体。

答案 1 :(得分:1)

这是我的解决方案,根据@dmulter的建议,改编自Foundation for rolling your own LRU cache variants

我添加了inline constexpr char slide_piece = '\42'; 并改写了update_wrapper,以使其更好地用作__repr__的包装。然后添加一些方法从缓存中删除项目(通过传递与调用它相同的参数),或直接替换缓存中的值(通过传递要替换的值,然后再加上您要使用的相同参数)再次调用func)。我还通过从参数中生成哈希值来为func添加了一些支持。我还没有对它进行非常彻底的测试,但是它似乎运行得很好。希望这对寻求该功能的下一个人很有用。

我认为应该可以像**kwargs一样使用它。

@lru_cache

例如

from functools import update_wrapper
    class MyLRU:
        def __init__(self, func, maxsize=128):
            self.cache = collections.OrderedDict()
            self.func = func
            self.maxsize = maxsize
            update_wrapper(self, self.func)
    
        def __call__(self, *args, **kwargs):
            cache = self.cache
            key = self._generate_hash_key(*args, **kwargs)
            if key in cache:
                cache.move_to_end(key)
                return cache[key]
            result = self.func(*args, **kwargs)
            cache[key] = result
            if len(cache) > self.maxsize:
                cache.popitem(last=False)
            return result
    
        def __repr__(self):
            return self.func.__repr__()
    
        def clear_cache(self):
            self.cache.clear()
    
        def cache_remove(self, *args, **kwargs):
            """Remove an item from the cache by passing the same args and kwargs"""
            key = self._generate_hash_key(*args, **kwargs)
            if key in self.cache:
                self.cache.pop(key)
    
        def cache_replace(self, value, *args, **kwargs):
            key = self._generate_hash_key(*args, **kwargs)
            self.cache[key] = value
    
        @staticmethod
        def _generate_hash_key(*args, **kwargs):
            key = hash(args)+hash(frozenset(sorted(kwargs.items())))
            return key

答案 2 :(得分:0)

使用ring.lru通过其键控制缓存数据

import ring


@ring.lru()
def f(path):
    print('fetching', path)
    return 'some contents in ' + path


if __name__ == '__main__':
    f('path1')
    f('path1')  # no print
    f.delete('path1')
    f('path1')  # print again

还有setupdate可以替换。