Как я могу игнорировать значения Unicode и сохранить формат '\ x ##'? - PullRequest
3 голосов
/ 12 июня 2019

Я работаю над созданием пакетов для последовательной отправки на устройство.Я хочу сохранить форматирование в том виде, в котором я его набрал, без преобразования в символы Юникод.

my_thing = b'\xb4\x75'
print(my_thing)
(Actual Output)>>> b'\xb4u'
(Wanted Output)>>> b'\xb4\x75'

Возможно, простой вопрос, но после поиска в Google и поиска других вопросов я не смог найти то, что искал,Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 12 июня 2019

Предполагая, что это только проблема с представлением / печатью, я предложу пользовательскую функцию печати:

my_thing = b'\xb4\x75'

def print_bytes_as_hex(b):
    print("b'{}'".format(''.join(r'\x{:02x}'.format(i) for i in b)))

print_bytes_as_hex(my_thing)

если вы скопируете / оцените вывод этой функции, он должен == ввести ее.

ПРИМЕЧАНИЕ: генерируемая строка является не == для входа.

0 голосов
/ 13 июня 2019

Когда вы набираете что-то вроде thing = b"\xb4", то, что хранится в Python, объект кода после компиляции - это просто фактическое число 0xb4 (180 в десятичном виде).Это не имеет никакого отношения к Юникоду вообще - фактически, разделение байтов и текстовых строк в Python 3 было сделано точно так, что значения байтов - это одно, а текст - другое, и для «привязки» нужно связать их сother.

Ваше значение будет таким же, как если бы вы сделали:

In [155]: thing = bytes([180])                                                                                                                         

In [156]: thing                                                                                                                                        
Out[156]: b'\xb4'

Это становится символом в Python 3 только в случае преобразования в строку с помощью явной кодировки:

In [157]: print(thing.decode("latin1"))                                                                                                                
´

Что происходит, так это то, что при некотором сходстве с самим языком Python 2 и C байтовые значения, которые оказываются отображенными в диапазон [32, 128], печатаются как символы ASCII.Итак, 0x75 соответствует символу ASCII u - но внутреннее представление обоих чисел в my_thing = b'\xb4\x75' по-прежнему представляет собой одно байтовое числовое значение для каждого - независимо от того, каково их представление с print.И когда вы отправляете этот объект байтов в двоичном пакете, оба числа 0xb4 и 0x75 будут отправлены как числовые значения.

Это легко проверить, если вы итерируете байтовую строку, которая выдает числовые значения в диапазоне [0, 256], или записываете значения в файл и проверяете, что он на самом деле содержит только 2 байта.:

In [158]: my_thing = b"\xb4\x75"                                                                                                                       

In [159]: my_thing                                                                                                                                     
Out[159]: b'\xb4u'

In [160]: list(my_thing)                                                                                                                               
Out[160]: [180, 117]

In [161]: open("test.bin", "wb").write(my_thing)                                                                                                       
Out[161]: 2

In [162]: !ls -la test.bin                                                                                                                             
-rw-rw-r--. 1 gwidion gwidion 2 Jun 13 17:46 test.bin

(«2» в последней строке в этом листинге - это размер файла в байтах, указанный в «ls» оболочки Linux)

Итак, единственная проблемау вас есть, если таковые имеются, возможность визуализировать ваши значения на стороне Python, прежде чем они будут отправлены - для этой цели, а затем для просмотра значений в консоли хоста, либо в виде распечатки в TTY, либо в виде графического интерфейса пользователя, либоСгенерировав веб-страницу, вы делаете противоположную вещь, которую, как вы думаете, происходит: Вызовите метод, который дает вам текстовый объект, представляющий HEX-цифры вашего байтового объекта в виде текста - так, чтобы его можно было легко проверить.У самого объекта байтов есть метод .hex(), который подходит для этой цели:

In [165]: my_thing.hex()                                                                                                                               
Out[165]: 'b475'

Итак, вот вам - шестнадцатеричные числа для 2 байтов, которые вы готовы отправить в виде пакета, рассматриваемые как текст - в то время каксодержимое самого my_thing не изменяется.

Это не имеет префикса "\xYY", поэтому лучше смотреть - и, если вы введете много значений, есть также метод байтов, который преобразует каждую пару шестнадцатеричных цифрв байт - и это гораздо удобнее для ввода буквенных значений.bytes.fromhex метод класса.Это позволяет вам набирать:

In [166]:my_thing = bytes.fromhex("b475")                                                                                                                        

И это эквивалентно b"\xb4\x75".

Если по какой-то причине вам действительно нужен префикс \x для каждой пары цифр, однострочный код Python может манипулировать им для генерации строки, содержащей литерал байтовой строки, который может быть передан eval, например - но использование bytes.fromhex все равно будет более читабельным:

converter = lambda seq: 'b"{}"'.format("".join(f"\\x{value:x}" for value in seq))

А в интерактивном сеансе:

In [168]: my_thing = b"\xb4\x75" 
     ...:  
     ...: converter = lambda seq: 'b"{}"'.format("".join(f"\\x{value:x}" for value in seq)) 
     ...: print(converter(my_thing))                                                                                                                   
b"\xb4\x75"

Это всего лишь распечатка текстовой строки- последовательность текстовых символов, включая символы «b», «» и т. д. Для возврата байтовых букв необходимо применить eval:

In [169]: eval(converter(my_thing))                                                                                                                    
Out[169]: b'\xb4u'
...