我正在考虑创建像dbms引擎这样的持久存储的想法,直接cPickling对象和/或使用shelve模块创建自定义二进制格式有什么好处?
答案 0 :(得分:10)
酸洗是一个两面硬币。
一方面,您可以通过一种非常简单的方式存储对象。只需要四行代码就可以了。你有完全相同的对象。
另一方面,它可能成为兼容性的噩梦。如果未在代码中定义对象,则无法对其进行解除对象,就像在pickle时定义的那样。这极大地限制了您重构代码或重新排列模块中的内容的能力。 此外,并非所有东西都可以被腌制,如果你对腌制的东西不严格并且你的代码的客户完全自由地包含任何对象,迟早它会将一些不可打击的东西传递给你的系统,系统将会繁荣
对它的使用要非常小心。没有更好的快速和肮脏的定义。
答案 1 :(得分:3)
定义自己的自定义二进制格式的一个原因可能是优化。 pickle(和shelve,使用pickle)是一个通用的序列化框架;它几乎可以存储任何Python数据。在很多情况下很容易使用pickle,但是检查所有对象并序列化它们的数据需要时间,而数据本身则以通用,冗长的格式存储。如果要存储特定的已知数据,则定制的序列化程序可以更快,更简洁。
用一个整数值来挑选一个对象需要37个字节:
>>> import pickle >>> class Foo: pass... >>> foo = Foo() >>> foo.x = 3 >>> print repr(pickle.dumps(foo)) "(i__main__\nFoo\np0\n(dp1\nS'x'\np2\nI3\nsb."
嵌入在该数据中的是属性的名称及其类型。 Foo(和Foo)的自定义序列化器可以省去它,只需存储数字,节省时间和空间。
自定义序列化框架的另一个原因是您可以轻松地进行数据的自定义验证和版本控制。如果您更改对象类型并需要加载旧版本的数据,那么通过pickle可能会非常棘手。您可以轻松自定义您自己的代码以处理较旧的数据格式。
在实践中,我使用通用cPickle模块构建一些东西,只有在分析表明它非常重要时才替换它。维护单独的序列化框架是一项重要的工作。
您可能会发现有用的最终资源:some synthetic serializer benchmarks。 cPickle非常快。
答案 2 :(得分:2)
请注意,并非所有对象都可以直接腌制 - 只有基本类型或已定义pickle协议的对象 使用您自己的二进制格式将允许您存储任何类型的对象。
请注意,Zope Object DB(ZODB)遵循同样的方法,使用Pickle格式存储对象。您可能有兴趣获得他们的实现。
答案 3 :(得分:1)
自定义格式相对于泡菜的潜在优势是:
这些优势是否实现取决于您如何设计存储空间。
答案 4 :(得分:1)
如果你要这样做(实现你自己的二进制格式),你应该首先知道python有一个很好的库来处理HDF5,这是一种在物理和天文学中用来转储大量数据的二进制格式。
这是图书馆的主页:
基本上,您可以将HDF5视为一个分层数据库,其中一个表列可以自己包含一个内部表:表Populations有一个名为Individual的列,它是一个包含每个人的信息的表,等等。 ..
PyTables也有自己的cPickle模块实现,您可以通过以下方式访问它:
$ easy_install tables
$ python
>>> import tables
>>> tables.cPickle
我从来没有使用pytable的泡菜,但我认为你可以直接了解它是如何工作的,所以你可以在实现自己的格式之前先看看它。
答案 5 :(得分:1)
在SourceForge上查看此解决方案:
y_serial.py module ::使用SQLite的仓库Python对象
“序列化+持久性::在几行代码中,将Python对象压缩并注释为SQLite;然后通过关键字按时间顺序检索它们,而不使用任何SQL。最有用的”标准“模块,用于存储无模式数据的数据库。“
http://yserial.sourceforge.net
[源尾注释中包含的评论讨论了为什么选择pickle而不是json。]
答案 6 :(得分:0)
您是否需要处理来自不受信任来源的数据?如果是这样,你应该知道pickle格式实际上是一个能够代表进行unpickling的进程执行任意代码的虚拟机。