Python 3.x numpy数组cPickle dumpe的默认编码是否为latin-1?

Python 3.x numpy数组cPickle dumpe的默认编码是否为latin-1?,python-3.x,encoding,utf-8,dump,iso-8859-1,Python 3.x,Encoding,Utf 8,Dump,Iso 8859 1,numpy数组cPickle dumpe的默认编码是否为latin-1?如果是,我在哪里可以得到确认。对于其余部分,它似乎是utf-8编码。这在numpy.array中失败 In [45]: b = cPickle.dumps(('.'.join(('test',)), (numpy.array([1007261]), True, True), {}), protocol=0)

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), {})

[45]中的
b=cPickle.dumps(('.'.join('test',),(numpy.array([1007261]),True,True),{},协议=0)
在[46]中:

Out[46]:b'(Vtest\np0\n(cnumpy.core.multiarray\n\u restruction\np1\n

当您从
pickle.dumps
的输出(即
b
in-Out[46])转到下一条语句中分配给
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
。 从视觉上看,您删除了字符串文本的
b
前缀。 实际上,您使用拉丁语1将
字节
对象解码为
str
。 这是因为Latin-1具有字节值到Unicode代码点的1:1映射

现在它是一个
str
。 但是pickle需要一个
bytes
对象,所以需要再次编码。 但是,如果使用UTF-8进行编码,将得到一个与原始对象不同的
字节
对象:

>>> b.decode('latin1').encode('utf8')
b'(V\xc2\x9d^\x0f'
您现在拥有的不是
\x9d
,而是
\xc2\x9d

如果使用拉丁语-1编码,则得到与之前相同的结果:

>>> b.decode('latin1').encode('latin1')
b'(V\x9d^\x0f'
但是:我不太明白为什么需要这种往返转换。 实际上,不需要将
pickle.dump的输出解码为
str
。 您可以一直将值保存在字节字符串中。
使用正确的类型:
bytes
用于二进制数据(如pickle dump),
str
用于文本(与pickle dump不同)。

实际上,这些字节,Out[46]通过隧道传输,接收器将假定它为字符串。因此我需要编码(将其转换为字节)然后解开它,但是如果它是二进制数据,为什么接收者会认为它是一个字符串呢?你不是数据的接收者并且可以控制发生了什么吗?注意:假设它是一个字符串意味着在这里将它转换为
str
,据我所知。这与解码是一样的。如果你不能阻止解码步骤,你需要要知道哪个编解码器用于解码(拉丁语-1,UTF-8…),您可以无损地转换回。