猿问

如何创建一个其值在文件重新加载后仍然存在的变量?

Common Lisp 有defvarwhich 创建一个全局变量,但只有在它是新的时才设置它:如果它已经存在,则不会重置。这在从长时间运行的交互式进程重新加载文件时很有用,因为它会保留数据。


我想在 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?

附注。我想我可以遵循如何检查变量是否存在?:


if 'cache' not in globals():

   cache = {}

但由于某种原因它看起来不像“Pythonic”......如果它是TRT,请告诉我!


慕标琳琳
浏览 164回答 2
2回答

PIPIONE

这里有几个选项。一种是使用临时文件作为缓存的持久存储,并在每次加载模块时尝试加载:# foo.pyimport tempfileimport pathlibimport 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 resdef _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.pyCache = {}进而:# foo.pyimport foo_cachedef expensive(x):    try:        return foo_cache.Cache[x]    except KeyError:        # do a lot of work        foo_cache.Cache[x] = res        return res

aluckdog

由于重新加载的全部目的是确保执行的模块的代码第二次运行,因此基本上无法避免某种“重新加载检测”。您使用的代码似乎是您参考的问题中给出的最佳答案。
随时随地看视频慕课网APP

相关分类

Python
我要回答