Правильная кодировка для отправки данных - PullRequest
0 голосов
/ 29 марта 2020

Некоторые вещи, которые были тривиальны в Python 2, становятся немного более утомительными в Python 3. Я посылаю строку, за которой следует какое-то шестнадцатеричное значение:

buffer = "ABCD"
buffer += "\xCA\xFE\xCA\xFE"

Это приводит к ошибке при отправке и я прочитал в другом посте, что решение состоит в том, чтобы использовать sendall и encode:

s.sendall(buffer.encode("UTF-8"))

Однако то, что посылается в сеть для шестнадцатеричного значения, кодируется в UTF-8:

c3 8a c3 be c3 8a c3 be

вместо точных байтов, которые я определил. Как мне сделать это без использования внешних библиотек и, возможно, без необходимости «конвертировать» данные в другую структуру?

Я знаю, что этот вопрос широко задавался, но я не могу найти удовлетворительное решение

Ответы [ 2 ]

2 голосов
/ 29 марта 2020

Вы можете подумать, что Python 3 усложняет задачу, но подразумевается обратное. У вас возникла проблема с применением кодировки. В python 2 было несколько причин путать с кодировками UTF-8 и Unicode. Теперь это исправлено.

Прежде всего, если вам нужно отправить двоичные данные, лучше выбрать тип ad-ho c, который равен bytes. Используя Python 3, достаточно префикс вашей строки с b. Это должно решить вашу проблему:

buffer = b"ABCD"
buffer += b"\xCA\xFE\xCA\xFE"
s.sendall(buffer)

Конечно, у объекта bytes нет метода encode, поскольку он уже закодирован в двоичный файл. Но у него есть обратный метод decode.

Когда вы создаете объект str, используя кавычки без префикса, по умолчанию Python 3 будет использовать кодировку Unicode (которая была применена принудительно) типом unicode или префиксом u в Python 2). Это означает, что вам потребуется использовать метод encode для получения двоичных данных.

Вместо этого непосредственно используйте bytes для хранения двоичных данных, поскольку не будет выполняться операция кодирования, и она останется такой, как вы ее набрали.

Ошибка can only concatenate str (not "bytes") to str говорит сама за себя. Python жалуется, что не может объединить str с bytes, поскольку прежние данные требуют дополнительного шага, а именно кодирования, чтобы сделать операцию + значимой.

1 голос
/ 29 марта 2020

Исходя из информации в вашем вопросе, вы могли бы быть в состоянии уйти с кодированием ваших данных как latin-1, потому что это не изменит какие-либо байтовые значения

buffer = "ABCD"
buffer += "\xCA\xFE\xCA\xFE"

payload = buffer.encode("latin-1")
print(payload)
b'ABCD\xca\xfe\xca\xfe'

С другой стороны, вы можете просто декодировать с латиницы-1:

buffer = payload.decode('latin-1')
buffer
'ABCDÊþÊþ'

Но вы можете предпочесть оставить текстовые и двоичные части вашего сообщения как их соответствующие типы:

encoded_text = payload[:4]
encoded_text
b'ABCD'
text = encoded_text.decode('latin-1')
print(text)
ABCD
binary_data = payload[4:]
binary_data
b'\xca\xfe\xca\xfe'

Если ваш текст содержит кодовые точки, которые не могут быть закодированы как латиница-1 - например, '你好 , 世界' - вы можете использовать тот же подход, но вам нужно будет кодировать текст как UTF-8 при кодировании двоичных данных как ' латино-1' ; Получающиеся байты нужно будет разбить на их текстовые и двоичные разделы и декодировать отдельно.

Наконец: кодирование строковых литералов, таких как '\xca\xfe\xca\xfe', является плохим стилем в Python3 - лучше объявить их как байтовые литералы, такие как b'\xca\xfe\xca\xfe'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...