如何从字节中创建一个numpy ndarray?

时间:2017-12-04 16:27:03

标签: python numpy

我可以使用myndarray.tobytes()将numpy ndarray转换为字节现在我怎样才能将它恢复为ndarray?

使用.tobytes()方法docs:

中的示例
>>> x = np.array([[0, 1], [2, 3]])
>>> bytes = x.tobytes()
>>> bytes
b'\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'

>>> np.some_magic_function_here(bytes)
array([[0, 1], [2, 3]])

3 个答案:

答案 0 :(得分:3)

编辑后,你似乎走错了方向!

当仅需要从这些字节进行重建时,您无法使用 np.tobytes() 来存储包含形状和类型等所有信息的完整数组!它只会保存原始数据(单元格值)并在C或Fortran顺序中展平它们。

现在我们不知道你的任务。但是你需要基于序列化的东西。有很多方法,最简单的是基于python的pickle(例如:python3!):

import pickle
import numpy as np

x = np.array([[0, 1], [2, 3]])
print(x)

x_as_bytes = pickle.dumps(x)
print(x_as_bytes)
print(type(x_as_bytes))

y = pickle.loads(x_as_bytes)
print(y)

输出:

[[0 1]
 [2 3]]
 b'\x80\x03cnumpy.core.multiarray\n_reconstruct\nq\x00cnumpy\nndarray\nq\x01K\x00\x85q\x02C\x01bq\x03\x87q\x04Rq\x05(K\x01K\x02K\x02\x86q\x06cnumpy\ndtype\nq\x07X\x02\x00\x00\x00i8q\x08K\x00K\x01\x87q\tRq\n(K\x03X\x01\x00\x00\x00<q\x0bNNNJ\xff\xff\xff\xffJ\xff\xff\xff\xffK\x00tq\x0cb\x89C \x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00q\rtq\x0eb.'
<class 'bytes'>
[[0 1]
 [2 3]]

更好的选择是joblib's pickle,对大型阵列进行专门的酸洗。 joblib的函数是基于文件对象的,并且可以使用python&#39; s BytesIO在内存中使用字节字符串。

答案 1 :(得分:2)

要反序列化字节,您需要np.frombuffer()
tobytes()将数组序列化为字节,而np.frombuffer()将其反序列化。

请记住,一旦序列化,形状信息就会丢失,这意味着在反序列化之后,需要将其重整为原始形状。

下面是一个完整的示例:

import numpy as np

x = np.array([[0, 1], [2, 3]], np.int8)
bytes = x.tobytes()
# bytes is a raw array, which means it contains no info regarding the shape of x
# let's make sure: we have 4 values with datatype=int8 (one byte per array's item), therefore the length of bytes should be 4bytes
assert len(bytes) == 4, "Ha??? Weird machine..."

deserialized_bytes = np.frombuffer(bytes, dtype=np.int8)
deserialized_x = np.reshape(deserialized_bytes, newshape=(2, 2))
assert np.array_equal(x, deserialized_x), "Deserialization failed..."

答案 2 :(得分:0)

如果您提前知道要重新创建的维度,请执行 numpy.ndarray(<dimensions>,<dataType>,<bytes(aka buffer)>)

x = numpy.array([[1.0,1.1,1.2,1.3],[2.0,2.1,2.2,2.3],[3.0,3.1,3.2,3.3]],numpy.float64)
#array([[1. , 1.1, 1.2, 1.3],
#       [2. , 2.1, 2.2, 2.3],
#       [3. , 3.1, 3.2, 3.3]])

xBytes = x.tobytes()
#b'\x00\x00\x00\x00\x00\x00\xf0?\x9a\x99\x99\x99\x99\x99\xf1?333333\xf3?\xcd\xcc\xcc\xcc\xcc\xcc\xf4?\x00\x00\x00\x00\x00\x00\x00@\xcd\xcc\xcc\xcc\xcc\xcc\x00@\x9a\x99\x99\x99\x99\x99\x01@ffffff\x02@\x00\x00\x00\x00\x00\x00\x08@\xcd\xcc\xcc\xcc\xcc\xcc\x08@\x9a\x99\x99\x99\x99\x99\t@ffffff\n@'

newX = numpy.ndarray((3,4),numpy.float64,xBytes)
#array([[1. , 1.1, 1.2, 1.3],
#       [2. , 2.1, 2.2, 2.3],
#       [3. , 3.1, 3.2, 3.3]])

另一种方法可能是,如果您将数据存储为字节记录而不是整个 ndarray,并且您选择的数据从 ndarray 到 ndarray 不同,您可以将预数组数据聚合为 python 字节数组中的字节,那么当它是所需的大小时,您已经知道所需的维度,并且可以将字节数组作为缓冲区提供这些维度/数据类型。