有没有Python缓存库?

问题描述:

我正在寻找一个Python缓存库,但到目前为止找不到任何东西。我需要一个简单的类似于dict的界面,我可以在其中设置键和过期时间并将其恢复缓存。排序是这样的:有没有Python缓存库?

cache.get(myfunction, duration=300) 

如果存在的话,这将给我的项目从缓存或调用函数并储存它,如果它没有或已过期。有人知道这样的事吗?

+0

我想你在你的例子中缺少'item'。 – SilentGhost 2009-09-15 13:45:03

+0

python 2.x或3.x? – 2009-09-15 13:49:54

+0

是的,这可能需要一个关键...而且,2.x. – 2009-09-15 13:50:44

+0

啊,我一直在寻找这个,所有我发现是一个维基提到如何将其用作WSGI中间件。它看起来像我需要的,谢谢。 – 2009-09-15 14:20:38

+6

另请参阅[dogpile](https://bitbucket.org/zzzeek/dogpile.cache) - 据说是新的和改进的烧杯。 – s29 2012-10-12 01:58:14

我觉得the python memcached API是普遍的工具,但我没有用它自己,我不确定它是否支持你需要的功能。

+3

这是行业标准,但我只想要一个简单的内存存储机制,可以存储100个左右的密钥,而memcached有点矫枉过正。不过谢谢你的回答。 – 2009-09-15 14:19:49

import time 

class CachedItem(object): 
    def __init__(self, key, value, duration=60): 
     self.key = key 
     self.value = value 
     self.duration = duration 
     self.timeStamp = time.time() 

    def __repr__(self): 
     return '<CachedItem {%s:%s} expires at: %s>' % (self.key, self.value, time.time() + self.duration) 

class CachedDict(dict): 

    def get(self, key, fn, duration): 
     if key not in self \ 
      or self[key].timeStamp + self[key].duration < time.time(): 
       print 'adding new value' 
       o = fn(key) 
       self[key] = CachedItem(key, o, duration) 
     else: 
      print 'loading from cache' 

     return self[key].value 



if __name__ == '__main__': 

    fn = lambda key: 'value of %s is None' % key 

    ci = CachedItem('a', 12) 
    print ci 
    cd = CachedDict() 
    print cd.get('a', fn, 5) 
    time.sleep(2) 
    print cd.get('a', fn, 6) 
    print cd.get('b', fn, 6) 
    time.sleep(2) 
    print cd.get('a', fn, 7) 
    print cd.get('b', fn, 7) 
+5

我做了这样的事情,但是您需要锁定多线程和大小参数以避免其无限增长。然后,你需要一些功能来通过访问来排序键来放弃最少访问的键等等。 – 2009-09-18 10:21:47

+0

__repr__行不正确(应使用self.timeStamp)。而且这是一个糟糕的实现,它不必要地为每个get()做数学运算。到期时间应该在CachedItem init中计算。 – ivo 2017-09-08 20:59:55

+0

事实上,如果你只是实现'get'方法,这不应该是一个字典子类,它应该是一个嵌入字典的对象。 – ivo 2017-09-08 21:31:40

您也可以查看Memoize decorator。你也许可以在没有太多修改的情况下做到你想做的事。

+0

这很聪明。一些更改和装饰者甚至可能会在一段时间后过期。 – 2013-10-20 02:04:49

+0

你完全可以在修饰器中为缓存写一个基于空间的限制。如果你想要一个函数,例如,按照术语生成斐波纳契序列,那将会很有帮助。你想缓存,但你只需要最后两个值 - 保存所有这些值只是空间效率低下。 – reem 2013-10-23 14:09:42

看gocept.cache

看bda.cache http://pypi.python.org/pypi/bda.cache - 使用ZCA并与Zope和BFG测试。

尝试redis,它是应用程序以原子方式共享数据的最清洁和最简单的解决方案之一,或者如果您有一些Web服务器平台。它非常容易设置,你将需要一个python redis客户端http://pypi.python.org/pypi/redis

你可以使用我的简单解决方案来解决这个问题。这实在是简单,没有任何幻想:

class MemCache(dict): 
    def __init__(self, fn): 
     dict.__init__(self) 
     self.__fn = fn 

    def __getitem__(self, item): 
     if item not in self: 
      dict.__setitem__(self, item, self.__fn(item)) 
     return dict.__getitem__(self, item) 

mc = MemCache(lambda x: x*x) 

for x in xrange(10): 
    print mc[x] 

for x in xrange(10): 
    print mc[x] 

它确实没有到期的funcionality,但是你可以用指定内存缓存中的C-TOR特定规则很容易的扩展。

希望代码足以说明问题,但如果不是这样,只要提到,缓存正在通过一个转换函数作为其中一个参数。它依次用于生成关于输入的缓存输出。

希望它可以帮助

+1

+1表示简单的建议。根据问题,这可能只是工作的工具。附:你不需要'__getitem__'中的'else' :) – hiwaylon 2013-05-26 12:50:41

+0

为什么他不需要'''__getitem__'''中的''''else''?这就是他填充字典的地方... – 2016-05-10 06:41:09

JOBLIBhttp://packages.python.org/joblib/支持缓存功能,在memoize的模式。大多数情况下,这个想法是缓存计算昂贵的功能。

>>> from joblib import Memory 
>>> mem = Memory(cachedir='/tmp/joblib') 
>>> import numpy as np 
>>> square = mem.cache(np.square) 
>>> 
>>> a = np.vander(np.arange(3)).astype(np.float) 
>>> b = square(a)         
________________________________________________________________________________ 
[Memory] Calling square... 
square(array([[ 0., 0., 1.], 
     [ 1., 1., 1.], 
     [ 4., 2., 1.]])) 
___________________________________________________________square - 0...s, 0.0min 

>>> c = square(a) 

你也可以做一些花哨的事情,比如在函数中使用@ memory.cache装饰器。文档在这里:http://packages.python.org/joblib/memory.html

+2

作为一个旁注,当你使用大型的NumPy数组时,joblib真的很闪亮,因为它有特殊的方法来处理它们。 – alexbw 2014-02-10 13:24:09

keyring是最好的python缓存库。您可以使用

keyring.set_password("service","jsonkey",json_res) 

json_res= keyring.get_password("service","jsonkey") 

json_res= keyring.core.delete_password("service","jsonkey") 
+0

这是一个钥匙圈库,而不是一个缓存库。 – 2013-10-23 17:20:56

+0

@StavrosKorokithakis实际上,我通过keyring – imp 2013-10-23 18:20:29

从Python 3.2开始,您可以使用functools库中的装饰器@lru_cache。 这是最近最近使用的缓存,所以其中的项目没有到期时间,但作为快速入侵,它非常有用。

from functools import lru_cache 

@lru_cache(maxsize=256) 
def f(x): 
    return x*x 

for x in range(20): 
    print f(x) 
for x in range(20): 
    print f(x) 
+12

[cachetools](https://pypi.python.org/pypi/cachetools)实现了对这些和它兼容的python 2和python 3的很好的实现缓存。 – vaab 2015-02-02 03:18:52

+0

big +1对于cachetools ...似乎很酷,有一个更多的缓存算法:) – 2015-04-08 13:15:05

+0

cachetools不是线程安全的,虽然 – roboslone 2015-07-21 07:38:02

尚未有人提及搁置。 https://docs.python.org/2/library/shelve.html

它不是memcached,但看起来更简单,可能适合您的需要。