Python pickle 的元素似乎缺失

Elements of a Python pickle seem to be missing

我继承了一些 python 代码,使用以下代码将其输出保存到泡菜中:

def save_picklefile_and_close(self):
    pickle.dump({'p_index': self.p_index, 'p_val': self.p_val,
                 'z': self.z, 'w': self.w, 'nd': self.nd, 'nfg': self.nfg,
                 'lamb_scalar': self.lamb_scalar, 'PEAKSIZE': self.PEAKSIZE,
                 'N': self.N, 'S': self.S, 'F': self.F,
                 'FG': self.FG, 'q': self.q,
                 'pi': self.pi, 'phi': self.phi,
                 'p_scores': self.p_scores, 'w_scores': self.w_scores, 'z_scores': self.z_scores,
                 'likelihood': self.likelihood,
                 'p_true_val': self.p_true_val,
                 'p_true_index': self.p_true_index,
                 'w_true': self.w_true,
                 'phi_true': self.phi_true,
                 'pi_true': self.pi_true,
                 'z_true': self.z_true,
                 'z_true_per_data': self.z_true_per_data,
                 'data_for_debugging': self.data_for_debugging,
                 }, self.picklefile)
    self.picklefile.close()

这在我看来就像是腌制的字典,网上有很多例子。所有的键都在 pickle 文件中,例如grep 'w_true' file.p returns 一场比赛。但是当我尝试用这段代码阅读泡菜时:

f = open('file.p')
p = pickle.load(f)
print "type=", type(p)
print "shape=", p.shape
print "w_true=", p.w_true

我得到的只是一个 numpy.ndarray:

type= <type 'numpy.ndarray'>
shape= (56, 147)
w_true=
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-39-83ddd085f0fd> in <module>()
      3 print "type=", type(p)
      4 print "shape=", p.shape
----> 5 print "w_true=", p.w_true

AttributeError: 'numpy.ndarray' object has no attribute 'w_true'

如何访问 pickle 中的其他信息?

更新: 是的,我肯定在使用同一个文件。本次修改代码:

f = open('/path/to/file.p', mode='rt')

p = pickle.load(f)
print "type=", type(p)
print "shape=", p.shape

i = 0
for line in f:
    if 'w_true' in line:
        print "line no.", i, ":", line
    i += 1

结果:

type= <type 'numpy.ndarray'>
shape= (56, 147)
line no. 7499 : sS'w_true'

但是没有理由字符串 w_true(以及 dict 中的所有其他键)应该在文件中,如果它是 只有 一个 ndarray,对吧?我唯一的另一个想法是,也许 pickle 文件头中有什么东西误导了 unpickler? IE。也许输出代码有问题?这是 file.p 的头像:

$ head -n25 file.p 
cnumpy.core.multiarray
_reconstruct
p1
(cnumpy
ndarray
p2
(I0
tS'b'
tRp3
(I1
(I56
I147
tcnumpy
dtype
p4
(S'i4'
I0
I1
tRp5
(I3
S'<'
NNNI-1
I-1
I0
tbI00

问题是创建 pickle 的代码只打开了一个文件:

self.picklefile = open(picklefile_name, 'wb')

然后两次写入同一个文件。首先在这里:

if self.is_saving_pickle:
    pickle.dump(self.x, self.picklefile) #a single numpy.ndarray

然后稍后在这里:

def save_picklefile_and_close(self):
    pickle.dump({'p_index': self.p_index, 'p_val': self.p_val,
                 # ... snip ...
                 'data_for_debugging': self.data_for_debugging,
                 }, self.picklefile)
    self.picklefile.close()

unpickler 开始加载 file.p 时,它看到并返回了第一个 pickle,然后在接触第二个之前停止了。当第一个 write pickle.dump() 调用被注释掉时,unpickling 正确 returns 来自第二个调用的 dict

更新: 根据@Mike McKerns 的评论和链接,也可以多次调用 pickle.load() 来检索多个 [=16] 制作的泡菜=] 在同一个文件中调用。