【问题标题】:Hook into pickle to obtain pre-binary representation?挂钩泡菜以获得预二进制表示?
【发布时间】:2021-01-28 15:36:08
【问题描述】:

如果我理解正确,pickle 将对象的状态转换为类似于dict 的东西,包括对象的类,然后将该数据写入二进制文件。获取对象的状态是通过complex interface 完成的,最简单的情况是访问对象的__dict__,但可能涉及到用户定义的方法,如__getstate__、__setstate__ 等。当一个 pickle 文件被加载时,二进制数据被读入类似dict 的表示,然后这些转换回对象。

我的问题: 是否有可能在获取对象状态之后但在写入二进制数据之前的点上挂钩pickle,并且在另一个方向上也是如此(在读取二进制数据之后但在恢复对象之前)?

背景:我正在考虑实现类似于jsonpickle 和hickle 的东西,即具有dump 和load 相同的接口,但使用另一种文件格式来存储数据(这里:JSON & HDF5 )。如果可能的话,我想避免重复 pickle 在访问和恢复对象状态时的长度,而是重用该部分,并且只创建一个新的“后端”。

使用dill 的解决方案同样好。

【问题讨论】:

    标签: python pickle dill


    【解决方案1】:

    如果您dumps 一个对象,并查看模块pickle.py:https://github.com/python/cpython/blob/3.9/Lib/pickle.py#L107,您会看到pickle 将一个对象转换为一系列操作码(以及递归存储的数据)。这基本上就是使用dump 时写入磁盘的内容。我编写了hickle 中存储任意对象的部分——首先使用dill.dumps 生成一串optcodes 和数据,然后使用HDF 存储该字符串。如果你在dill开启追踪,你可以看到操作码和数据是如何存储在字符串中的。

    >>> x = dict(a=[1,2,3], b=set((4,5,6)))
    >>> import dill
    >>> dill.detect.trace(True)
    >>> dill.dumps(x)
    D2: <dict object at 0x11023c870>
    T1: <class 'set'>
    F2: <function _load_type at 0x11070f2f0>
    # F2
    # T1
    # D2
    b'\x80\x03}q\x00(X\x01\x00\x00\x00aq\x01]q\x02(K\x01K\x02K\x03eX\x01\x00\x00\x00bq\x03cdill._dill\n_load_type\nq\x04X\x03\x00\x00\x00setq\x05\x85q\x06Rq\x07]q\x08(K\x04K\x05K\x06e\x85q\tRq\nu.'
    

    它创建一个字典,存储一个整数列表(不需要特殊函数),然后存储一个特殊函数 (load_type) 以帮助重构集合,最后存储整数集。开头的 Optcodes 表示版本和协议。

    所以,是的,您可以在将状态转储到文件之前访问状态(以序列化形式)。

    【讨论】:

    • 我想我不够清楚:我写的是“在写入二进制数据之前”,但实际上我的意思是“在转换为操作码序列之前”。经过一番摸索,我想像__reduce__ 返回的东西类似,除了它仍然包含没有明显存储形式的函数和类对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多