2 回答

TA贡献1829条经验 获得超9个赞
这里有几个选项。一种是使用临时文件作为缓存的持久存储,并在每次加载模块时尝试加载:
# foo.py
import tempfile
import pathlib
import pickle
_CACHE_TEMP_FILE_NAME = '__foo_cache__.pickle'
_CACHE = {}
def expensive(x):
try:
return _CACHE[x]
except KeyError:
# do a lot of work
_CACHE[x] = res
_save_cache()
return res
def _save_cache():
tmp = pathlib.Path(tempfile.gettempdir(), _CACHE_TEMP_FILE_NAME)
with tmp.open('wb') as f:
pickle.dump(_CACHE, f)
def _load_cache():
global _CACHE
tmp = pathlib.Path(tempfile.gettempdir(), _CACHE_TEMP_FILE_NAME)
if not tmp.is_file():
return
try:
with tmp.open('rb') as f:
_CACHE = pickle.load(f)
except pickle.UnpicklingError:
pass
_load_cache()
唯一的问题是您需要相信环境不会写入任何恶意内容来代替临时文件(该pickle模块对于错误或恶意构建的数据不安全)。
另一种选择是为缓存使用另一个模块,一个不会重新加载的模块:
# foo_cache.py
Cache = {}
进而:
# foo.py
import foo_cache
def expensive(x):
try:
return foo_cache.Cache[x]
except KeyError:
# do a lot of work
foo_cache.Cache[x] = res
return res

TA贡献1847条经验 获得超7个赞
由于重新加载的全部目的是确保执行的模块的代码第二次运行,因此基本上无法避免某种“重新加载检测”。
您使用的代码似乎是您参考的问题中给出的最佳答案。
添加回答
举报