一个numpy数组应该通过flask从python发送到JS。我不想对其进行JSON加密并发送,因为它会增加响应的大小,并最终增加响应时间。因此,我认为我可以使用tobytes()将numpy转换为字节,然后通过flask将字节发送给JS,然后再将字节转换回JS中的float值,并发现Converting a string of packed bytes into an array of floats in Javascript答案是有帮助的。
操作列表为
byte_arr = np.array([5.6], dtype=np.float32).tobytes() # Used one value just to make it simple
return byte_arr # Bytes can be directly sent from flask as response
在JS中,
str = response.text
bytes = Uint8Array.from(str, c => c.charCodeAt(0))
floats = new Float32Array(bytes.buffer)
但是在JS中转换为float时,我没有得到正确的值。调试时,我发现在JS中,Uint8数组中的某些值与python发送的字节值不匹配。
JS: console.log(bytes) // [51, 51, 255, 64]
Python: for val in byte_arr: print(val, end=" ") // 51, 51, 179, 64
为了验证,我在python中创建了另一个客户端,提出了相同的请求,并将响应字节转换为float。我也在这里遇到了同样的问题。因此,我缩小了范围,问题出在服务器端而不是客户端。使用多个值时,我发现另一件有趣的事情是,只有大于127的数字(我想是)才转换为255。
在尝试一些随机破解时,我尝试在发送响应之前使用python的chr()方法将字节整数转换为字符,并且在客户端进行转换。
byte_arr = np.array([5.6], dtype=np.float32).tobytes()
byte_arr_char = "".join([chr(i) for i in byte_arr])
return byte_arr_char
但是我的问题是,这是理想的解决方案,还是我在这里做了一些修改以使其工作?谁能帮助我了解为什么不使用chr()发送纯字节不起作用吗?
答案 0 :(得分:7)
如果您未明确设置MIME type,我认为Flask会将其视为文本数据。您的浏览器似乎已经用ASCII解码了二进制数据,这可以解释为什么只影响大于127的值。
因此,请尝试在Flask中设置响应的Content-Type
:
@app.route('/your/url/to/numpy/data')
def get_nparray():
your_np_array = np.array([5.6], dtype=np.float32)
response = flask.make_response(your_np_array.tobytes())
response.headers.set('Content-Type', 'application/octet-stream')
# response.headers.set('Content-Disposition', 'attachment', filename='np-array.bin')
return response
或者,有一个辅助函数flask.send_file
可以在一行中构造响应。请找到示例here。
除此错误外,还要注意二进制数据的endianness,它是特定于硬件的。我会向您介绍此answer( Javascript类型的数组和字节序)。