如何使用成员变量持久化Python类,这些成员变量也是具有大“numpy”数组变量的Python类(因此“pickle”



用例:Python类在一个有用的结构中存储大型numpy数组(很大,但足够小,在内存中使用它们很容易)。这是一幅关于这种情况的漫画:

主类:Environment;存储与所有球相关的有用信息

"child"类:Ball;存储与该特定球相关的信息

Environment成员变量:balls_in_environmentBall s列表)

Ball成员变量:large_numpy_array(NxN numpy数组很大,但在内存中仍然很容易使用)

我想最好把Environment作为一个整体来坚持。

一些选项:

  • pickle:太慢,它产生的输出占用了硬盘上的大量空间

  • 数据库:工作量太大;我可以将类中的重要信息存储在数据库中(需要我编写函数来从类中获取信息,并将其放入数据库),然后通过创建一个新实例来重建类,并用数据库中的数据重新填充它(需要我写函数来进行重建)

  • JSON:我对JSON不是很熟悉,但Python有一个标准库来处理它,这是本文推荐的解决方案——不过我不认为JSON会比pickle更紧凑;更重要的是,不能很好地处理numpy

  • MessagePack:上面提到的同一篇文章推荐的另一个包;然而,我从来没有听说过它,也不想用的标准问题来打击未知

  • numpy.save+其他东西:使用numpy.save功能存储与每个Ball关联的numpy数组,并以某种方式单独存储非numpy内容(乏味)?

我的用例的最佳选项是什么?

正如我在评论中提到的,joblib.dump可能是一个不错的选择。它使用np.save来有效地存储numpy数组,并使用cPickle来存储其他所有内容:

import numpy as np
import cPickle
import joblib
import os

class SerializationTest(object):
    def __init__(self):
        self.array = np.random.randn(1000, 1000)
st = SerializationTest()
fnames = ['cpickle.pkl', 'numpy_save.npy', 'joblib.pkl']
# using cPickle
with open(fnames[0], 'w') as f:
    cPickle.dump(st, f)
# using np.save
np.save(fnames[1], st)
# using joblib.dump (without compression)
joblib.dump(st, fnames[2])
# check file sizes
for fname in fnames:
    print('%15s: %8.2f KB' % (fname, os.stat(fname).st_size / 1E3))
#     cpickle.pkl: 23695.56 KB
#  numpy_save.npy:  8000.33 KB
#      joblib.pkl:     0.18 KB

一个潜在的缺点是,由于joblib.dump使用cPickle序列化Python对象,因此生成的文件无法从Python 2移植到Python 3。为了获得更好的可移植性,您可以考虑使用HDF5,例如在这里。

最新更新