在Python脚本运行之间将持久变量保留在内存中

mac*_*ing 51 python memory variables

有没有办法将结果变量保存在内存中,所以每次运行脚本的开头时我都不必重新计算它?每次运行脚本时,我都会对数据集(我从磁盘上读取)执行一系列(5-10秒)的精确操作.这不会是一个太大的问题,因为我很擅长使用交互式编辑器在运行之间调试我的代码; 但有时候,互动功能并没有削减它.

我知道我可以把我的结果写到磁盘上的文件中,但是如果可能的话,我想避免这样做.这应该是一个解决方案,它在我第一次运行脚本时生成一个变量,并将其保存在内存中,直到shell本身关闭或直到我明确告诉它失败.像这样的东西:

# Check if variable already created this session
in_mem = var_in_memory() # Returns pointer to var, or False if not in memory yet
if not in_mem:
    # Read data set from disk
    with open('mydata', 'r') as in_handle:
        mytext = in_handle.read()
    # Extract relevant results from data set
    mydata = parse_data(mytext)
    result = initial_operations(mydata)
    in_mem = store_persistent(result)
Run Code Online (Sandbox Code Playgroud)

我有一个暗示搁架模块可能就是我在这里寻找的东西,但看起来为了打开搁架变量我必须为持久对象指定一个文件名,所以我不确定是否这是我正在寻找的.

关于搁置做我想做的事的任何提示?还有其他想法吗?

Pet*_*ons 43

您可以使用reload全局函数重新执行主脚本的代码来实现这样的功能.您需要编写一个包装器脚本来导入您的主脚本,询问它要缓存的变量,在包装器脚本的模块范围内缓存它的副本,然后在您需要时(当您在stdin或其他任何地方点击ENTER时) ),它调用,reload(yourscriptmodule)但这次传递缓存的对象,以便yourscript可以绕过昂贵的计算.这是一个简单的例子.

wrapper.py

import sys
import mainscript

part1Cache = None
if __name__ == "__main__":
    while True:
        if not part1Cache:
            part1Cache = mainscript.part1()
        mainscript.part2(part1Cache)
        print "Press enter to re-run the script, CTRL-C to exit"
        sys.stdin.readline()
        reload(mainscript)
Run Code Online (Sandbox Code Playgroud)

mainscript.py

def part1():
    print "part1 expensive computation running"
    return "This was expensive to compute"

def part2(value):
    print "part2 running with %s" % value
Run Code Online (Sandbox Code Playgroud)

wrapper.py运行时,您可以编辑mainscript.py,向part2函数添加新代码,并能够针对预先计算的part1Cache运行新代码.

  • 很好的答案!对于Python3,在wrapper.py中包含:“from importlib import reload” (5认同)
  • 我会考虑添加一个异常处理程序,您可以在其中运行外部源. (3认同)
  • 不是没有重装,没有。当您的python进程死亡时,将清除环境。但是,使用上述机制,您可以将其存储在os.environ中,但是现在您将数据公开到进程外部,并且仅限于一定长度的字符串。通过使用简单的python变量,可以避免这些限制。 (2认同)

Ray*_*oal 7

Python 的 shelve 是腌制(序列化)对象的持久化解决方案,并且是基于文件的。优点是它直接存储Python对象,这意味着API非常简单。

如果您确实想避免使用磁盘,那么您正在寻找的技术就是“内存数据库”。存在几种替代方案,请参阅这个问题:Python 中的内存数据库


Die*_*Epp 6

要将数据保存在内存中,该进程必须继续运行.内存属于运行脚本的进程,而不属于shell.shell无法为您保存内存.

因此,如果您想更改代码并保持流程运行,则必须在更改模块时重新加载模块.如果内存中的任何数据是更改的类的实例,则必须找到将其转换为新类的实例的方法.这有点乱.没有多少语言能够在这种热补丁中获得任何好处(Common Lisp浮现在脑海中),并且有很多机会出错.


Mat*_*son 6

如果您只想在将来的会话中保留一个对象(或对象图),则搁置模块可能过度.只需腌制你关心的对象.如果没有pickle文件,请完成工作并保存pickle,如果有文件,则加载pickle文件.

import os
import cPickle as pickle

pickle_filepath = "/path/to/picklefile.pickle"

if not os.path.exists(pickle_filepath):
    # Read data set from disk
    with open('mydata', 'r') as in_handle:
        mytext = in_handle.read()
    # Extract relevant results from data set
    mydata = parse_data(mytext)
    result = initial_operations(mydata)
    with open(pickle_filepath, 'w') as pickle_handle:
        pickle.dump(result, pickle_handle)
else:
    with open(pickle_filepath) as pickle_handle:
        result = pickle.load(pickle_handle)
Run Code Online (Sandbox Code Playgroud)