有没有一种方法,以memoize的功能到磁盘的输出?
我有一个函数
def getHtmlOfUrl(url):
... # expensive computation
并愿做这样的事情:
def getHtmlMemoized(url) = memoizeToFile(getHtmlOfUrl, "file.dat")
然后调用getHtmlMemoized(URL),以便为每个URL做昂贵的计算一次。
有没有一种方法,以memoize的功能到磁盘的输出?
我有一个函数
def getHtmlOfUrl(url):
... # expensive computation
并愿做这样的事情:
def getHtmlMemoized(url) = memoizeToFile(getHtmlOfUrl, "file.dat")
然后调用getHtmlMemoized(URL),以便为每个URL做昂贵的计算一次。
python提供了非常优雅的方式来做到这一点 - 装饰。 基本上,一个装饰是包装另一个功能而不改变功能的源代码提供附加功能的功能。 你的装饰可以这样写:
import json
def persist_to_file(file_name):
def decorator(original_func):
try:
cache = json.load(open(file_name, 'r'))
except (IOError, ValueError):
cache = {}
def new_func(param):
if param not in cache:
cache[param] = original_func(param)
json.dump(cache, open(file_name, 'w'))
return cache[param]
return new_func
return decorator
一旦你得到了,“装饰”功能使用@ -syntax,你准备好了。
@persist_to_file('cache.dat')
def html_of_url(url):
your function code...
请注意,此装饰被有意简化,可能不适用于所有情况,例如,当源函数接受或返回不能JSON序列化的数据。
更多关于装饰: 如何使功能装饰链?
下面是如何使装饰保存缓存只有一次,在退出时间:
import json, atexit
def persist_to_file(file_name):
try:
cache = json.load(open(file_name, 'r'))
except (IOError, ValueError):
cache = {}
atexit.register(lambda: json.dump(cache, open(file_name, 'w')))
def decorator(func):
def new_func(param):
if param not in cache:
cache[param] = func(param)
return cache[param]
return new_func
return decorator
退房joblib.Memory
。 这正是出于这个做一个图书馆。
一个清洁的解决方案搭载Python的搁置模块。 其优点是通过缓存知名实时得到更新dict
语法,也很例外证明(无需处理烦人KeyError
)。
import shelve
def shelve_it(file_name):
d = shelve.open(file_name)
def decorator(func):
def new_func(param):
if param not in d:
d[param] = func(param)
return d[param]
return new_func
return decorator
@shelve_it('cache.shelve')
def expensive_funcion(param):
pass
这将有利于将只计算一次的功能。 接下来的后续调用将返回存储的结果。
像这样的东西应该做的:
import json
class Memoize(object):
def __init__(self, func):
self.func = func
self.memo = {}
def load_memo(filename):
with open(filename) as f:
self.memo.update(json.load(f))
def save_memo(filename):
with open(filename, 'w') as f:
json.dump(self.memo, f)
def __call__(self, *args):
if not args in self.memo:
self.memo[args] = self.func(*args)
return self.memo[args]
基本用法:
your_mem_func = Memoize(your_func)
your_mem_func.load_memo('yourdata.json')
# do your stuff with your_mem_func
如果你想使用它后写你的“缓存”的文件-要在未来再次加载:
your_mem_func.save_memo('yournewdata.json')
假设你的数据JSON序列化,这个代码应工作
import os, json
def json_file(fname):
def decorator(function):
def wrapper(*args, **kwargs):
if os.path.isfile(fname):
with open(fname, 'r') as f:
ret = json.load(f)
else:
with open(fname, 'w') as f:
ret = function(*args, **kwargs)
json.dump(ret, f)
return ret
return wrapper
return decorator
装饰getHtmlOfUrl
,然后简单地调用它,如果它之前已经运行,你会得到你的缓存数据。
经过与Python 2.x和Python 3.x都有
在Artemis的图书馆有这一个模块。 (你需要pip install artemis-ml
)
你装饰你的函数:
from artemis.fileman.disk_memoize import memoize_to_disk
@memoize_to_disk
def fcn(a, b, c = None):
results = ...
return results
在内部,它使一个哈希出的输入参数,并通过这个散列保存备忘文件。
您可以使用cache_to_disk包:
from cache_to_disk import cache_to_disk
@cache_to_disk(3)
def my_func(a, b, c, d=None):
results = ...
return results
这将缓存结果3天,具体到参数的a,b,c和d。 结果存储在一个文件泡菜您的机器上,和拆封并返回函数被调用下一次。 3天后,咸菜文件被删除,直到功能重新运行。 该功能将被重新运行每当函数调用新的论据。 更多资讯: https://github.com/sarenehan/cache_to_disk