应该通过flask从python向JS发送一个numpy数组。我不想对其进行 jsonify 化并发送,因为它会增加响应的大小并最终增加响应时间。所以我想我可以使用 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。
在尝试一些随机的 hack 时,我尝试在发送响应之前使用 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() 的纯字节不起作用?
最佳答案
如果你不设置 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 类型化数组和字节顺序)。
关于javascript - 通过 Flask 将 numpy 数组作为字节从 python 发送到 JS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54899367/