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

时间:2019-02-15 14:21:23

标签: python python-3.x persistent-storage

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,请告诉我!

正在回答的评论:

  • 我对交叉调用持久化不感兴趣。我 am 已经处理了。
  • am 痛苦地意识到,重新加载会更改类元对象,而我 am 已经在处理它。
  • cache中的值很大,每次需要时我都无法进入磁盘。

2 个答案:

答案 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)

由于重新加载的全部目的是确保已执行模块的代码第二次运行,因此基本上没有办法避免某种“重新加载检测”。

您使用的代码似乎是您所参考问题给出的最佳答案。