Послать массив numy в виде байтов из python в JS через Flask - PullRequest
0 голосов
/ 27 февраля 2019

Numpy массив должен быть отправлен из Python в JS через колбу.Я не хочу jsonify это и отправить, поскольку это увеличило бы размер ответа и в конечном счете время ответа.Поэтому я подумал, что смогу преобразовать numy в байты с помощью tobytes (), отправить байты в JS через flask и преобразовать байты обратно в float в JS и нашел Преобразование строки упакованных байтов в массив с плавающей точкой в ​​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)

Но при конвертации в float в JS я не получаю правильныйценности.При отладке я обнаружил, что в 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.

При попытке случайного взлома я попытался преобразовать байтцелое число в символе с использованием метода chr () python перед отправкой ответа и преобразование на стороне клиента сработало.

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 () не работает?

1 Ответ

0 голосов
/ 02 марта 2019

Если вы явно не установите тип MIME , я думаю, что Flask будет воспринимать его как текстовые данные.Похоже, ваш браузер расшифровал двоичные данные с помощью ASCII, что может объяснить, почему были затронуты только значения, превышающие 127.

Поэтому, пожалуйста, попробуйте установить Content-Type ответа в Flask:

@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 для построения ответа в одной строке.Пожалуйста, найдите пример здесь .

Помимо этой ошибки, также обратите внимание на endianness ваших двоичных данных, который зависит от оборудования.Я хотел бы отослать вас к этому ответу ( Типизированные массивы Javascript и Endianness ).

...