一年多前,我报告了一个错误我在腌制一些相当复杂的数据时遇到了这个错误。当时我不知道问题是什么,并相信它可能与递归引用有关。
我在处理项目时多次遇到这个问题,但只是尝试修复它,直到错误消失。现在我终于花时间深入研究问题的根源并完善我的 MWE。这就是我想到的:
import pickle
import numpy as np
# create data
dtypes = [('f0', 'O')]
# for some reason, I need at least an extra of 19 fields for it to crash
# immediately
dtypes += [(f'f{i+1}', 'i4') for i in range(19)]
data = np.empty(1, dtype=dtypes)
# print(data[0])
# dump data
dump = pickle.dumps(data[0], pickle.HIGHEST_PROTOCOL)
# print('dumping works')
# load data
load = pickle.loads(dump)
# print('loading works')
# process crashes here if len(dtypes) > 19
print(load)
# process prints random data, e.g.
# (((...), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 0, 0,
# -1931060898, 32763, 1472326776, 503, 1482667496, 503, 0, 0, 1484270024,
# 503, 1472326776, 503, -1930803631, 32763, 1484270024, 503)
# or
# ((((((...), False, True), False, True), dtype('int32'), None), 0, 0), 0, 0)
# or
# (((...), <cell at 0x0000017018A25888: str object at 0x000001701AF998F0>,
# <cell at 0x0000017019084498: bool object at 0x00007FFB8D0EA970>,
# <cell at 0x00000170190842B8: int object at 0x00007FFB8D16A270>,
# <cell at 0x000001701927E2E8: str object at 0x0000017018989BB0>,
# <cell at 0x0000017018A3E798: bool object at 0x00007FFB8D0EA970>),
# 0, 0, -1931060898, 32763, 451341512)
# and crashes immediately afterwards if 2 <= len(dtypes) <= 19.
# process finishes with exit code 0 if data has no additional fields except f0,
# and prints
# (((...),),)
现在我知道过去也报告过类似的问题:
pickling/unpickling numpy.void 和 numpy.record 用于多处理
在最近的一个非常相似的案例中
似乎已经引入了a fix,但是我的代码仍然导致崩溃:
Process finished with exit code -1073741819 (0xC0000005)
现在对于 Python - numpy.void 对象的 pickling 失败,接受的答案是 jottos 的评论(2009 年 12 月 29 日 18:42):
因此,pickling 仅适用于顶级模块函数和类,并且不会 pickle 类数据,因此,如果需要某些 numpy 类代码/数据来生成 numpy void 类型的表示,pickling 将无法按预期工作。 numpy 包可能已经实现了一个内部 repr 将 void 类型打印为元组,如果是这种情况,那么您腌制的肯定不会是您打印的。
但这已经是十多年前的事了,似乎从那时起就引入了错误修复。那么这仍然是这里正在发生的事情,还是有别的原因?特别是因为我的代码显示出如此任意的行为。
Windows:10 Home,v.21H1,内部版本 19043.1288
PyCharm:2021.2(专业版),版本#PY-212.4746.96
Python(通过 anaconda):3.7.7 [MSC v.1916 64 位 (AMD64)]
Numpy:1.19.2
泡菜:4.0
将 numpy.void 转换为字典:将 numpy.void 数据转换为字典以与 pickle 兼容。
序列化到文件: 转换后的字典使用pickle序列化并保存到文件中。
从文件反序列化 字典从文件中读回并恢复为 pythonnative 格式。