使用Python经常更新数值实验的存储数据

时间:2014-06-27 16:52:51

标签: python pickle numerical-methods

我正在进行一项需要多次迭代的数值实验。在每次迭代之后,我想将数据存储在pickle文件或类似pickle的文件中,以防程序超时或数据结构被点击。什么是最好的方法。这是骨架代码:

data_dict = {}                       # maybe a dictionary is not the best choice
for j in parameters:                 # j = (alpha, beta, gamma) and cycle through
    for k in number_of_experiments:  # lots of experiments (10^4)
        file = open('storage.pkl', 'ab')
        data = experiment()          # experiment returns some numerical value
                                     # experiment takes ~ 1 seconds, but increase
                                     # as parameters scale
        data_dict.setdefault(j, []).append(data)
        pickle.dump(data_dict, file)
        file.close()

问题:

  1. 这里有更好的选择吗?还是我不知道的其他一些python库?
  2. 我正在使用数据字典,因为如果我需要在进行更多实验时更改内容,它更容易编码并且更灵活。使用预先分配的阵列会是一个巨大的优势吗?
  3. 打开和关闭文件会影响运行时间吗?我这样做是为了除了我设置的文本日志外,还可以查看进度。
  4. 感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

  1. 假设您使用numpy进行数值实验,而不是pickle我建议使用numpy.savez
  2. 保持简单,只有在您认为脚本运行时间过长时才进行优化。
  3. 打开和关闭文件会影响运行时间,但最好还是备份。
  4. 我会使用collections.defaultdict(list)代替普通dictsetdefault

答案 1 :(得分:1)

Shelve可能不是一个好选择,但是......

您可以尝试使用kleptojoblib。两者都擅长缓存结果,并且可以使用高效的存储格式。

joblibklepto都可以将结果保存到磁盘上的文件或目录中。如果您愿意,两者还可以利用numpy内部存储格式和/或压缩保存...并保存到内存映射文件。

如果使用klepto,则将字典键作为文件名,并将值保存为内容。使用klepto,您还可以选择是否要使用picklejson或其他一些存储格式。

Python 2.7.7 (default, Jun  2 2014, 01:33:50) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import klepto
>>> data_dict = klepto.archives.dir_archive('storage', cached=False, serialized=True)     
>>> import string
>>> import random
>>> for j in string.ascii_letters:
...   for k in range(1000):
...     data_dict.setdefault(j, []).append([int(10*random.random()) for i in range(3)])
... 
>>> 

这将创建一个名为storage的目录,其中包含pickle文件,每个密钥对应data_dict。有关于使用memmap文件的关键字,也有压缩级别的关键字。如果选择cached=False,那么每次写入data_dict时都不会转储到文件中,而是每次都写入内存...然后您可以使用data_dict.dump()转储到磁盘你选择...或者你可以选择一个内存限制,当你点击它时,你将转储到磁盘。此外,您还可以选择缓存策略(如lrulfu)来决定从内存中清除哪些密钥并转储到磁盘。

在此处获取kleptohttps://github.com/uqfoundation

或在此处获取joblibhttps://github.com/joblib/joblib

如果你重构,你可能想出办法来做到这一点,这样它就可以利用预先分配的数组。但是,它可能取决于代码运行方式的配置文件。

打开和关闭文件会影响运行时间吗?是。如果使用klepto,则可以设置要转储到磁盘的粒度。然后,您可以选择速度与结果的中间存储之间的权衡。