代码之家  ›  专栏  ›  技术社区  ›  amirouche

不使用cpickle为数据创建持久存储的好处是什么?

  •  5
  • amirouche  · 技术社区  · 17 年前

    我正在考虑创建一个像DBMS引擎一样的持久存储的想法,通过直接点击对象和/或使用搁置模块来创建自定义二进制格式有什么好处?

    7 回复  |  直到 11 年前
        1
  •  9
  •   Stefano Borini    17 年前

    腌渍是一种两面派的硬币。

    一方面,你有一种非常简单的方法来存储你的物品。只要四行代码,你就可以泡菜了。你拥有的对象和它完全一样。

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

    小心使用。没有更好的定义快速和肮脏。

        2
  •  3
  •   Nelson    17 年前

    定义自定义二进制格式的一个原因可能是优化。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)可以省去这个问题,只需存储数字,节省时间和空间。

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

    在实践中,我会使用通用的cpickle模块构建一些东西,并且仅在概要分析表明它非常重要时才替换它。维护单独的序列化框架是一项重要的工作。

    最后一个有用的资源是: some synthetic serializer benchmarks . CPickle相当快。

        3
  •  2
  •   rob    17 年前

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

    请注意,zope对象数据库(zodb)采用了同样的方法,以pickle格式存储对象。您可能对获得它们的实现感兴趣。

        4
  •  1
  •   Martin v. Löwis    17 年前

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

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

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

        5
  •  1
  •   dalloliogm    17 年前

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

    这是库的主页:

    基本上,您可以将hdf5看作是一个分层数据库,其中一个表列本身可以包含一个内部表:表填充有一个称为Individual的列,它是一个包含每个人的信息的表,等等…

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

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

    我从未使用过Pytable的pickle,但我认为您可以直接了解它的工作原理,因此在实现自己的格式之前,您可以先看看它。

        6
  •  1
  •   code43    17 年前

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

    y_serial.py模块::使用sqlite的仓库python对象

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

    http://yserial.sourceforge.net

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

        7
  •  0
  •   Marius Gedminas    17 年前

    您是否需要处理来自不可信来源的数据?如果是这样,您应该知道pickle格式实际上是一个虚拟机,它能够代表执行解压的进程执行任意代码。

    推荐文章