挂钩泡菜以获得预二进制表示?

问题描述

如果我理解正确,pickle 会将对象的状态转换为 dict 之类的内容包括对象的类,然后将该数据写入二进制文件获取对象的状态是通过 complex interface 完成的,在最简单的情况下访问对象的 __dict__,但可能涉及用户定义的方法,如 __getstate____setstate__ 等。 .加载 pickle 文件时,二进制数据会被读取为类似 dict 的表示形式,然后这些表示形式会转换回对象。

我的问题:是否有可能在获取对象状态之后但在写入二进制数据之前的点上挂钩到 pickle数据但在恢复对象之前)?

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

使用 dill解决方案也一样好。

解决方法

如果您 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.'

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

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