假设我有一个pickle转储 - 无论是作为文件还是作为字符串 - 如何确定用于自动创建pickle转储的协议?
如果是这样,我是否需要读取整个转储以找出协议或者是否可以在O(1)中实现?通过O(1)我想到一些标题信息在pickle字符串或文件的开头,其读出不需要处理整个转储。
非常感谢!
编辑:我有一个更新,显然下面给出的答案并不总是在python 3.4下工作。如果我只是用协议1来挑选值True
,有时我只能恢复协议0: - /
答案 0 :(得分:2)
您可以使用picketools
with open('your_pickle_file', 'rb') as fin:
op, fst, snd = next(pickletools.genops(fin))
proto = op.proto
PROTO标记似乎只写为协议为2或更大的第一个元素。否则,第一个元素是指示协议是0还是1的标记或元素。
更新到kludging更多土地:
pops = pickletools.genops(pickle_source)
proto = 2 if next(pops)[0].proto == 2 else int(any(op.proto for op, fst, snd in pops))
答案 1 :(得分:1)
2020年更新:
我在这里尝试了这些方法(来自@JonClements的回答和评论),但似乎没有一个给我正确的协议。
但是,以下工作原理:
proto = None
op, fst, snd = next(pickletools.genops(data))
if op.name == 'PROTO':
proto = fst
替代方法(不酷,因为它使整个过程脱皮):
out = io.StringIO()
pickletools.dis(data, out)
firstline = out.getvalue().splitlines()[0]
if ' PROTO ' in firstline:
proto = re.sub(r'.*\s+', '', firstline)
proto = int(proto)
应用程序:我想找出在pandas.to_hdf()
中使用了哪种腌制协议(如果使用了腌制,但并非总是如此),并且由于我不想分析它的整个结构HDF5文件,我正在使用MonkeyPatch
监视pickle.loads()
要求反序列化的内容。
无论谁通过Google搜索降落在这里,这就是我的整个设置(糊涂):
__pickle_loads = pickle.loads
def mock_pickle_loads(data):
global max_proto_found
op, fst, snd = next(pickletools.genops(data))
if op.name == 'PROTO':
proto = fst
max_proto_found = max(max_proto_found, proto)
return __pickle_loads(data)
def max_pklproto_hdf(hdf_filename):
global max_proto_found
max_proto_found = -1
with MonkeyPatch().context() as m:
m.setattr(pickle, 'loads', mock_pickle_loads)
try:
pd.read_hdf(hdf_filename)
except ValueError:
pass
return max_proto_found