为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕标琳琳 2021-11-09 20:11:50
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,请告诉我!
查看完整描述

2 回答

?
PIPIONE

TA贡献1829条经验 获得超9个赞

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


# 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


查看完整回答
反对 回复 2021-11-09
?
aluckdog

TA贡献1847条经验 获得超7个赞

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

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


查看完整回答
反对 回复 2021-11-09
  • 2 回答
  • 0 关注
  • 163 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信