Lisp公用有defvar
,其中
创建一个全局变量,但仅在新变量时设置:如果已经存在
存在,不重置。在长时间运行的交互式过程中重新加载文件时,这很有用,因为它可以保留数据。
我想要在Python中也一样。
我有foo.py
文件,其中包含以下内容:
cache = {}
def expensive(x):
try:
return cache[x]
except KeyError:
# do a lot of work
cache[x] = res
return res
当我执行imp.reload(foo)
时,我想要的cache
的值丢失了
避免。
cache
中保持reload
?PS 。我想我可以关注How do I check if a variable exists?:
if 'cache' not in globals():
cache = {}
但是由于某种原因,它看起来不是“ Pythonic” ... 如果是 TRT,请告诉我!
cache
中的值很大,每次需要时我都无法进入磁盘。答案 0 :(得分:2)
这里有两个选择。一种是使用临时文件作为缓存的持久存储,并在每次加载模块时尝试加载:
# 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
答案 1 :(得分:0)
由于重新加载的全部目的是确保已执行模块的代码第二次运行,因此基本上没有办法避免某种“重新加载检测”。
您使用的代码似乎是您所参考问题给出的最佳答案。