lru_cache-是否可以仅清除缓存中的特定调用?

时间:2019-06-02 08:28:50

标签: python

我了解cache_clear。但是,我想知道如何清除单个呼叫的缓存。看到cache_clear不接受参数,我认为唯一的方法是直接弄乱基础字典。会有什么副作用(如果有)?

目标是实现以下目标

from functools import lru_cache

@lru_cache()
def f(x):
    print('called with ', x)


f(1)
f.cache_clear(1)  # obviously does not work
f(1)

带有输出

called with  1
called with  1

2 个答案:

答案 0 :(得分:1)

这应该被认为是不可能的。没有公用的API,根本没有访问缓存的属性,也没有统一的缓存键格式。即使您采取了严厉的措施(gc / ctypes来获取高速缓存,您也可能会破坏整个LRU系统,到处泄漏大量内存,甚至可能出现段错误。 implementation中的内存管理在面对直接破坏缓存的人时并不安全。

答案 1 :(得分:0)

我成功地为 Python redis 支持的 lru 缓存装饰器实现了一个细粒度的 cache_clear() - 参见 gist。这是 lru_cache 的一种与 Python 3 附带的完全不同的实现,我可以理解它的内部结构并进行必要的更改。

特别是,cache_clear() 得到了增强,因此如果您传递参数,缓存将被部分清除 - 仅针对该特定调用签名。这确实允许更精细的缓存清除。

在此过程中,我学到了一些很深的东西,这为这次讨论提供了一些启示,这可能是 Python 3 没有采用细粒度缓存清除的一个原因。

我发现这种增强的 cache_clear() 行为需要非常小心使用,因为同时 例如f(1)f(param=1) 意思相同,lru 缓存系统会缓存那些 两个调用作为单独的条目。然后当你使一种调用方式无效时 f.cache_clear(1) 这使得另一种调用方式 f(param=1) 仍然被缓存并且 返回陈旧的值 - 即使在语义上这两种调用风格是 相同的。因此,如果您确实精细地使用 cache_clear,请确保重复调用它 您可能使用过的所有可能的参数签名,例如f.cache_clear(1); f.cache_clear(param=1)

我想可能有一种算法可以计算出等效的参数 (*args, **kwargs) 的所有可能排列?那么这种细粒度的缓存清除方法使用起来会安全得多。