numpy数组cPickle dumpe的默认编码是latin-1吗?如果是这样,我可以在哪里得到确认。其余的似乎都是utf-8编码。 numpy.array失败]
In [45]: b = cPickle.dumps(('.'.join(('test',)), (numpy.array([1007261]), True, True), {}), protocol=0)
In [46]: b
Out[46]: b'(Vtest\np0\n(cnumpy.core.multiarray\n_reconstruct\np1\n(cnumpy\nndarray\np2\n(I0\ntp3\nc_codecs\nencode\np4\n(Vb\np5\nVlatin1\np6\ntp7\nRp8\ntp9\nRp10\n(I1\n(I1\ntp11\ncnumpy\ndtype\np12\n(Vi8\np13\nI0\nI1\ntp14\nRp15\n(I3\nV<\np16\nNNNI-1\nI-1\nI0\ntp17\nbI00\ng4\n(V\x9d^\x0f\\u0000\\u0000\\u0000\\u0000\\u0000\np18\ng6\ntp19\nRp20\ntp21\nbI01\nI01\ntp22\n(dp23\ntp24\n.'
In [47]: b = '(Vtest\np0\n(cnumpy.core.multiarray\n_reconstruct\np1\n(cnumpy\nndarray\np2\n(I0\ntp3\nc_codecs\nencode\np4\n(Vb\np5\nVlatin1\np6\ntp7\nRp8\ntp9\nR
...: p10\n(I1\n(I1\ntp11\ncnumpy\ndtype\np12\n(Vi8\np13\nI0\nI1\ntp14\nRp15\n(I3\nV<\np16\nNNNI-1\nI-1\nI0\ntp17\nbI00\ng4\n(V\x9d^\x0f\\u0000\\u0000\\u0000\
...: \u0000\\u0000\np18\ng6\ntp19\nRp20\ntp21\nbI01\nI01\ntp22\n(dp23\ntp24\n.'
In [48]: cPickle.loads(b.encode('utf-8'), encoding='utf-8')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-48-58c17196f700> in <module>
----> 1 cPickle.loads(b.encode('utf-8'), encoding='utf-8')
ValueError: buffer size does not match array size
In [50]: cPickle.loads(b.encode('latin1'), encoding='latin1')
Out[50]: ('test', (array([1007261]), True, True), {})
我正在从一个应用程序转储数据,并从另一个应用程序读取数据。因此,在使用cPickle加载字符串之前,必须将字符串转换为字节。我虽然cPickle.dump总是在py3中使用utf-8编码,这让我感到奇怪。有人可以给我一些启示。
不是泡菜,首先是您使用Latin-1。
当您从pickle.dumps
的输出转到将Out [46]中的b
更改为在下一条语句中分配给b
的值,然后将类型从bytes
更改为str
。进行此更改的方式等效于b = b.decode('latin1')
。
例如,原始b
包含序列b'(V\x9d^\x0f'
(在最后三分之一中)。让我们用它来看看发生了什么:
>>> b = b'(V\x9d^\x0f'
>>> b.decode('latin1')
'(V\x9d^\x0f'
这是您在语句47中分配给b
的内容(接近第二行的末尾)。Visually,您删除了字符串文字的b
前缀。有效地,您使用Latin-1将bytes
对象解码为str
。这是因为Latin-1具有字节值与Unicode代码点的1:1映射。
现在是str
。但是pickle需要一个bytes
对象,因此您需要再次编码。但是,如果您使用UTF-8进行编码,则会得到一个与原始对象不同的bytes
对象:
>>> b.decode('latin1').encode('utf8')
b'(V\xc2\x9d^\x0f'
您现在有了\x9d
,而不是\xc2\x9d
。
如果您使用Latin-1进行编码,则会获得与以前相同的效果:
>>> b.decode('latin1').encode('latin1')
b'(V\x9d^\x0f'
但是:我不太明白为什么这种往返转换是完全必要的。确实不需要将pickle.dumps
的输出解码为str
。您可以一直将值保留在字节字符串中。请使用正确的类型:bytes
用于二进制数据(如泡菜转储),str
用于文本(与泡菜转储不同)。