Common 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 中的值很大,我不能每次需要它们时都去磁盘。
  • 最佳答案

    这里有几个选项。一种是使用临时文件作为缓存的持久存储,并在每次加载模块时尝试加载:

    # 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
    

    关于python - 如何创建一个其值在文件重新加载后仍然存在的变量?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54711295/

    10-12 00:22
    查看更多