是初学者。对不起,如果我的问题幼稚。 python中的cachetools是否可以进行后续运行?

import cachetools
import time


@cachetools.cached({})
def find_sum(n):
    time.sleep(5)
    return n+2


print find_sum(2)
print find_sum(3)
print find_sum(2)

因此,在第一次运行期间,第三次调用的速度更快,但是在下次运行文件时,我希望第一次调用的速度更快,并从缓存中获取结果。 cachetools可以做到吗?

最佳答案

cachetools 不能开箱即用。但这很容易添加。

您可以将所需的任何可变映射传递给memoizing decorators。您使用的是普通的旧字典,而字典对于腌制来说是微不足道的。即使您使用该库提供的精美cache implementations之一,它们也很容易腌制。1

所以:

import cachetools
import pickle
import time

try:
    with open('mycache.pickle', 'rb') as f:
        cache = pickle.load(f)
except FileNotFoundError:
    cache = {} # or cachetools.LRUCache(maxsize=5) or whatever you want

@cachetools.cached(cache)
def find_sum(n):
    time.sleep(5)
    return n+2

print(find_sum(2))
print(find_sum(3))
print(find_sum(2))

with open('mycache.pickle', 'wb') as f:
    pickle.dump(cache, f)

当然,您可以添加:
  • 一个finally或上下文管理器或atexit,即使遇到异常或^ C,也可以确保在关闭时保存文件。
  • 一个计时器,经常保存它们。
  • 缓存对象上的钩子,用于在每次更新或每N次更新时保存。 (只需重写__setitem__方法,或者,如果使用更高级的类之一而不是dict,则可以查看Extending cache classes进行其他操作。)


  • 或者,您甚至可以将磁盘键值数据库用作缓存。

    最简单的数据库是 dbm 。键和值都限于str / bytes。 (如果要使用非字符串值,则可以使用 shelve ;如果要使用非字符串键,则可能需要其他解决方案。)因此,对于我们的示例而言,这不太可行。但是对于一个类似的例子,这几乎是魔术:
    import dbm
    import time
    import cachetools
    
    cache = dbm.open('mycache.dbm', 'c')
    @cachetools.cached(cache, key=lambda s:s)
    def find_string_sum(s):
        time.sleep(5)
        return s + '!'
    
    print(find_string_sum('a'))
    print(find_string_sum('b'))
    print(find_string_sum('a'))
    

    唯一棘手的一点是我必须重写key函数。 (默认键函数处理*args, **kw,因此对于参数'a',您最终会得到类似(('a',), ())的内容,这显然不是字符串。)

    1.从the source可以看到,已进行了一些错误修复,以确保所有类在所有受支持的Python版本中都是可腌制的,因此,这显然是故意的。

    08-25 00:56