将 python 浮点数转换为字节

Converting python float to bytes

我想将 Python 浮点数转换为字节数组,将其编码为 32 位小端 IEEE 浮点数,以便将其写入二进制文件。

在 Python 3 中,现代 Pythonic 方法是什么?对于整数我可以做 my_int.to_bytes(4,'little'),但是没有 to_bytes 浮点数方法。

如果我可以一次为 numpy 数组(使用 dtype numpy.float32)中的每个浮点数执行此操作,那就更好了。但请注意,我需要将其作为字节数组获取,而不是立即将数组写入文件。

有一些听起来很相似的问题,但它们似乎主要是关于获取十六进制数字,而不是写入二进制文件。

NumPy 数组带有一个 tobytes 方法,可以为您转储其原始数据字节:

arr.tobytes()

您可以指定一个 order 参数来为多维数组使用 C 阶(行优先)或 F 阶(列优先)。

既然要转储字节到文件,可能对tofile方法也感兴趣,直接转储字节到文件:

arr.tofile(your_file)

tofile 总是使用 C 顺序。

如果需要改变字节顺序,可以使用byteswap方法。 (newbyteorder有一个更方便的签名,但不改变底层字节,所以不会影响tobytes。)

import sys
if sys.byteorder=='big':
    arr = arr.byteswap()
data_bytes = arr.tobytes()

使用正确的 dtype 可以将数组的数据缓冲区写入字节串或二进制文件:

In [449]: x = np.arange(4., dtype='<f4')                                        
In [450]: x                                                                     
Out[450]: array([0., 1., 2., 3.], dtype=float32)
In [451]: txt = x.tostring()                                                    
In [452]: txt                                                                   
Out[452]: b'\x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00@\x00\x00@@'
In [453]: x.tofile('test')                                                                                                                           
In [455]: np.fromfile('test','<f4')                                             
Out[455]: array([0., 1., 2., 3.], dtype=float32)
In [459]: with open('test','br') as f: print(f.read())                          
b'\x00\x00\x00\x00\x00\x00\x80?\x00\x00\x00@\x00\x00@@'

改变结局:

In [460]: x.astype('>f4').tostring()                                            
Out[460]: b'\x00\x00\x00\x00?\x80\x00\x00@\x00\x00\x00@@\x00\x00'

numpy中有save/savez个方法:

将数据存储到磁盘,然后再次加载:

>>> np.save('/tmp/123', np.array([[1, 2, 3], [4, 5, 6]]))
>>> np.load('/tmp/123.npy')
array([[1, 2, 3],
       [4, 5, 6]])

将压缩数据存储到磁盘,并再次加载:

>>> a=np.array([[1, 2, 3], [4, 5, 6]])
>>> b=np.array([1, 2])
>>> np.savez('/tmp/123.npz', a=a, b=b)
>>> data = np.load('/tmp/123.npz')
>>> data['a']
array([[1, 2, 3],
       [4, 5, 6]])
>>> data['b']
array([1, 2])
>>> data.close()

您可以使用 structpack bytes 之类的

>>> import struct
>>> struct.pack('<f', 3.14) # little-endian
b'\xc3\xf5H@'
>>> struct.pack('>f', 3.14) # big-endian
b'@H\xf5\xc3'