【问题标题】:How can I make a numpy ndarray from bytes?如何从字节制作一个 numpy ndarray?
【发布时间】:2017-12-04 16:27:02
【问题描述】:

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

使用.tobytes() 方法文档中的示例:

>>> 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]])

【问题讨论】:

标签: python numpy


【解决方案1】:

要反序列化您需要的字节,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】:

    在您的编辑之后,您似乎走错了方向!

    您不能使用 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 的BytesIO 在内存中使用字节字符串。

    【讨论】:

      【解决方案3】:

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

      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 bytearray 中的字节,那么当它是所需的大小时,您已经知道所需的尺寸,并且可以将这些尺寸/数据类型与 bytearray 作为缓冲区一起提供。

      【讨论】:

        猜你喜欢
        • 2021-07-28
        • 2021-10-15
        • 2016-02-10
        • 2016-11-19
        • 2018-06-05
        • 1970-01-01
        • 1970-01-01
        • 2016-03-23
        • 2018-10-10
        相关资源
        最近更新 更多