在Python脚本运行之间保持内存中的持久variables

有没有办法在内存中保留一个结果variables,所以我不必每次运行我的脚本的开始时重新计算它? 每当我运行我的脚本时,我正在对一个数据集(我正在从磁盘读取)进行一系列长的(5-10秒)的精确操作。 这不会是太多的问题,因为我非常擅长使用交互式编辑器在运行之间debugging我的代码; 然而有时交互function不能削减它。

我知道我可以把结果写到磁盘上的文件中,但是如果可能的话,我想避免这样做。 这应该是一个解决scheme,它在我第一次运行脚本时生成一个variables,并将其保存在内存中,直到shell本身closures,或者直到我明确地告诉它为止。 像这样的东西:

# 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) 

我有一个暗示搁置模块可能是我在这里寻找,但看起来像要打开搁置variables我将不得不指定一个文件名为持久对象,所以我不知道如果这正是我正在寻找的。

任何提示搁置做我想做的事情? 任何替代的想法?

你可以使用reload全局函数来重新执行主脚本的代码。 你将需要编写一个包装脚本来导入你的主脚本,请求它为它想要caching的variables,在包装脚本的模块范围内caching一个副本,然后当你想要的时候),它调用reload(yourscriptmodule)但是这次传递caching的对象,这样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) 

mainscript.py

 def part1(): print "part1 expensive computation running" return "This was expensive to compute" def part2(value): print "part2 running with %s" % value 

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

如果您只想为将来的会话保留一个对象(或对象图),则搁置模块可能是矫枉过正的。 只是腌你关心的对象。 如果没有泡菜文件,请做好工作并保存泡菜,或者如果有泡菜文件,请加载泡菜文件。

 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) 

Python的搁置是对pickled(序列化)对象的持久化解决scheme,并且是基于文件的。 其优点是它直接存储Python对象,这意味着API非常简单。

如果你真的想避开磁盘,那么你正在寻找的技术是一个“内存数据库”。 有几个替代scheme,请参阅这个问题: Python中的内存数据库 。

为了将数据保存在内存中,进程必须保持运行。 内存属于运行脚本的进程,而不属于shell。 shell不能为你保存内存。

所以,如果你想改变你的代码,并保持你的进程运行,你将不得不重新加载模块,当他们改变。 如果内存中的任何数据是一个类的实例发生了变化,则必须find一种方法将其转换为新类的实例。 这有点乱。 在这种热补丁(Common Lisp想到)方面,没有多less语言能够胜任,而且出现错误的机会也很多。

这是一个os依赖的解决scheme…

 $mkfifo inpipe #/usr/bin/python3 #firstprocess.py complicated_calculation() while True: with open('inpipe') as f: try: print( exec (f.read())) except Exception as e: print(e) $./first_process.py & $cat second_process.py > inpipe 

这将允许您在第一个进程中更改和重新定义variables,而无需复制或重新计算任何内容。 与多处理,memcached,pickle,搁置模块或数据库相比,它应该是最有效的解决scheme。

如果你想在你的编辑器或者IDE中迭代地编辑和重新定义second_process.py,那么这是非常好的,直到你拥有了它,而不需要等待第一个进程(例如初始化一个大的字典等)更改。

你可以这样做,但是你必须使用一个Python shell。 换句话说,用来启动Python脚本的shell必须是一个Python进程。 然后,任何全局variables或类将一直存在,直到closuresshell。

看看cmd模块,这可以很容易地编写一个shell程序。 你甚至可以这样安排,以便任何在你的shell中没有实现的命令都被传递到系统shell执行(不closures你的shell)。 那么你将不得不实施某种types的命令,例如prun ,它使用runpy模块来运行Python脚本。

http://docs.python.org/library/runpy.html

您需要使用init_globals参数将特殊数据传递给程序的名称空间,理想情况下是字典或单个类实例。

您可以通过加载/计算的操作系统在服务器上运行持久性脚本,甚至可以定期将sql数据重新加载/重新计算到某种内存结构中,然后通过套接字从另一个脚本中获取内存中的数据。