Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 关于反序列化某些数字的问题(错误??)_Python_Numpy_Pickle - Fatal编程技术网

Python 关于反序列化某些数字的问题(错误??)

Python 关于反序列化某些数字的问题(错误??),python,numpy,pickle,Python,Numpy,Pickle,为了反序列化bytes对象,我们使用pickle.loads() 预期结果如下所示(因为np.float64(0.34103)不是bytes对象,所以预期会出现适当的错误) 仅当转换的字节以b'\x88开头时(例如0.04263、0.08526、0.11651…)才会发生此情况 有人能回答这个问题是否是Python bug吗 任何答案都将不胜感激。这不是Python错误pickle.loads可与any一起使用,numpy float就是其中之一。 从一开始,字节就是这样工作的:字节表示没有类型

为了反序列化bytes对象,我们使用pickle.loads()

预期结果如下所示(因为np.float64(0.34103)不是bytes对象,所以预期会出现适当的错误)

仅当转换的字节以b'\x88开头时(例如0.04263、0.08526、0.11651…)才会发生此情况

有人能回答这个问题是否是Python bug吗


任何答案都将不胜感激。

这不是Python错误<代码>pickle.loads可与any一起使用,numpy float就是其中之一。
从一开始,字节就是这样工作的:字节表示没有类型的原始数据。表示numpy float
0.34104
的8个字节恰好与表示Python pickle
True
的8个字节匹配,这纯粹是巧合

对于特定的pickle协议2,
b'\x88.\xa8o\x99\xd3\xd5?
恰好是
True
、pickle结束和被忽略的尾部垃圾的操作码

pickletools.dis(b'\x88.\xa8o\x99\xd3\xd5?) 0:\x88新路 1: . 停止
例如,“numpy float
0.34104
”的字节模式也匹配小端无符号/有符号Python整数
4599815250385579656
、大端无符号Python整数
9812965835362522431
、大端有符号Python整数
-8633778238347029185
,拉丁文字符串
'\x88.¨o\x99ÓÕ?'
和许多其他值

>int.from_字节(np.float64(0.34103),byteorder='big',signed=False)
13915064561919317311

pickle.load
的输入不限于
字节
对象。引用

返回对象的pickle表示数据的重构对象层次结构。数据必须是有效的

并引用“类似字节的对象”

支持并可以导出C连续缓冲区的对象

缓冲区协议是对象向其他代码公开其底层内存缓冲区的一种方式,适用于有意义的对象。NumPy数组支持缓冲区协议,允许其他代码在数组的底层存储上操作,而无需执行昂贵的Python级索引操作和包装对象。NumPy标量也支持缓冲协议,以尽可能无缝地处理0维数据


pickle.loads(np.float64(0.34103))的错误不是因为
np.float64(0.34103)
不是字节。如果您试图传入一个普通的
float
,您会得到一个类型错误,因为该类型无效(
float
s与字节不同),但是对于
np.float64(0.34103)
,您得到的错误是因为
pickle.loads
尝试读取
np.float64(0.34103)的缓冲区
并发现其中的数据不是有效的pickle


对于
np.float64(0.34104)
,缓冲区的内容恰好是一个有效的pickle。侥幸的是,字节恰好匹配一个NEWTRUE操作码、一个STOP操作码和被忽略的尾部垃圾。NEWTRUE在
pickle
堆栈上推送一个True,停止pickle执行,返回True。

tobytes
np.frombuffer
配对,将
pickle.dumps
pickle.loads配对。您尝试的配对没有意义。我在您的代码示例中没有看到
tobytes
。我的意思是“np.float64(0.34104)。tobytes()”为我们提供了以b'x88开头的二进制表达式。此数字打印为真,而不是错误。有人能解释这种现象吗?为什么要尝试
pickle.load(x)
其中
x
不是pickle字节字符串?该协议并不是为接收这种随机数据而设计的。Python通常不是这样处理字节的。这里有特定的NumPy功能与pickle.load进行交互。大多数对象永远不会被这样解释。您的说法是,之所以会发生这种情况,是因为“字节就是这样工作的:字节是没有类型的原始数据。”,但Python不会将
字节
视为“没有类型的原始数据”,而且它不会将任意对象的内存表示形式重新解释为字节。如果您尝试将大多数对象传递给
pickle.loads
,它将立即引发类型错误,而不会尝试执行任何类型的字节解释。您的答案立即跳转到(错误的)关于pickle协议和
numpy.float64(0.34104)
内存布局的断言,甚至没有考虑
pickle.loads
将此对象视为有效输入的原因。这一点以及
pickle.loads
像对象一样使用字节的事实。我对这个问题的解释是,最重要的一点是为什么
pickle
甚至接受不是
bytes
实例的对象-这个问题表达了一种期望,即非
bytes
输入会引发错误。我很高兴我们能够澄清这一点。(错误的断言是字节与“表示Python pickle True的8字节”匹配的断言,好像只有一个pickle解pickle到
True
,而这8个字节与该pickle匹配。您的编辑也修复了此问题。)
import pickle
import numpy as np
pickle.loads(np.float64(0.34103))
---------------------------------------------------------------------------
UnpicklingError Traceback (most recent call last)
<ipython-input-19-5c07606a60f1> in <module>
----> 1 pickle.loads(np.float64(0.34103))

UnpicklingError: invalid load key, '\xc1'.
pickle.loads(np.float64(0.34104))
True
np.float64(0.34104).tobytes()
b'\x88.\xa8o\x99\xd3\xd5?'