Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 不使用cPickle为数据创建持久存储有什么好处?_Python_Database_Data Structures_Persistence - Fatal编程技术网

Python 不使用cPickle为数据创建持久存储有什么好处?

Python 不使用cPickle为数据创建持久存储有什么好处?,python,database,data-structures,persistence,Python,Database,Data Structures,Persistence,我正在考虑创建一个类似dbms引擎的持久性存储的想法,创建自定义二进制格式比直接打包对象和/或使用搁置模块有什么好处?请注意,并非所有对象都可以直接pickle-只有基本类型或定义了pickle协议的对象。 使用您自己的二进制格式将允许您存储任何类型的对象 值得注意的是,Zope对象数据库(ZODB)也遵循同样的方法,使用Pickle格式存储对象。您可能对它们的实现感兴趣。酸洗是一种双面硬币 一方面,您有一种非常简单的方法来存储对象。只需要四行代码,就可以进行pickle。您拥有的对象与它的原样

我正在考虑创建一个类似dbms引擎的持久性存储的想法,创建自定义二进制格式比直接打包对象和/或使用搁置模块有什么好处?

请注意,并非所有对象都可以直接pickle-只有基本类型或定义了pickle协议的对象。
使用您自己的二进制格式将允许您存储任何类型的对象


值得注意的是,Zope对象数据库(ZODB)也遵循同样的方法,使用Pickle格式存储对象。您可能对它们的实现感兴趣。

酸洗是一种双面硬币

一方面,您有一种非常简单的方法来存储对象。只需要四行代码,就可以进行pickle。您拥有的对象与它的原样完全相同

另一方面,它可能成为兼容性的噩梦。如果对象未在代码中定义,则无法取消拾取对象,这与pickle时定义的完全相同。这严重限制了您重构代码或重新安排模块中的内容的能力。 而且,不是所有的东西都可以被pickle,如果你对被pickle的东西不严格,并且你的代码的客户端可以完全自由地包含任何对象,那么它迟早会将一些不可pickle的东西传递给你的系统,系统就会崩溃


使用时要非常小心。“快”和“脏”没有更好的定义。

与pickle相比,自定义格式的潜在优势是:

  • 您可以有选择地获取单个对象,而不必具体化整个对象集
  • 您可以按属性查询对象子集,并仅加载符合条件的对象

当然,这些优势是否实现取决于您如何设计存储。

定义自定义二进制格式的一个原因可能是优化。pickle(和shelve,它使用pickle)是一个通用的序列化框架;它几乎可以存储任何Python数据。在很多情况下使用pickle很容易,但是检查所有对象并序列化它们的数据需要时间,并且数据本身以通用的详细格式存储。如果您存储的是特定的已知数据,那么定制的序列化程序可以更快、更简洁

使用单个整数值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=foo() >>>foo.x=3 >>>打印报告(pickle.dumps(foo)) “(i\uuuu main\uuuuo\np0\n(dp1\nS'x'\np2\nI3\nsb)。” 数据中嵌入的是属性的名称及其类型。一个自定义的Foo序列化程序(仅Foo一个)可以省去这些,只存储数字,节省时间和空间

自定义序列化框架的另一个原因是,您可以轻松地对数据进行自定义验证和版本控制。如果更改对象类型并需要加载旧版本的数据,则通过pickle可能会很棘手。您可以轻松地自定义自己的代码以处理旧的数据格式

在实践中,我会使用通用的cPickle模块构建一些东西,并且只有在分析表明它非常重要时才替换它


您可能会发现最后一个有用的资源:.cPickle非常快。

如果您要这样做(实现您自己的二进制格式),您首先应该知道python有一个很好的库来处理HDF5,HDF5是物理学和天文学中用来转储大量数据的二进制格式

这是图书馆的主页:

基本上,您可以将HDF5视为一个分层数据库,其中一个表列本身可以包含一个内部表:表填充有一个名为“个体”的列,该列是一个包含每个个体信息的表,等等

PyTables也有自己的cPickle模块实现,您可以通过以下方式访问它:

$ easy_install tables
$ python
>>> import tables
>>> tables.cPickle

我从未使用过pytable的pickle,但我认为学习它的工作原理可能很简单,因此在实现自己的格式之前,您可以先看看它。

您是否需要处理来自不可信来源的数据?如果是,您应该知道pickle格式实际上是一个能够执行代表执行取消勾选的进程的任意代码。

请参阅SourceForge上的此解决方案:

y_serial.py模块::使用SQLite存储Python对象

序列化+持久性::在几行代码中,将Python对象压缩并注释到SQLite中;然后在不使用任何SQL的情况下按时间顺序按关键字检索它们。这是数据库存储无模式数据的最有用的“标准”模块


[源尾注中的注释讨论了为什么选择pickle而不是json。]

pickle可以处理大多数用户定义的类,而无需额外的代码。在某些情况下,您只需定义pickle协议的特殊处理。如果它使用pickle,则对于基于web的项目不安全,仅此而已?y_serial only unpickle取消由其自身函数创建的受信任pickle,因此它是安全的。您应该阅读模块itse中的尾注lf给出了详细的解释。