如何创建一个其值在文件重新加载时保持不变的变量?

问题描述 投票:4回答:2

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的价值丢失了,我想避免。

How do I keep cache across reload?

PS。我想我可以关注How do I check if a variable exists?

if 'cache' not in globals():
   cache = {}

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

回答评论:

  • 我对交叉调用持久性不感兴趣;我已经处理过了。
  • 我痛苦地意识到重新加载更改了类元对象,我已经在处理它了。
  • cache中的值很大,每次我需要时都无法访问磁盘。
python python-3.x persistent-storage
2个回答
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

0
投票

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

您使用的代码似乎是您引用的问题中给出的最佳答案。

© www.soinside.com 2019 - 2024. All rights reserved.