struct pack, печатающая строку вместо двоичного значения - PullRequest
1 голос
/ 30 апреля 2019

Почему мой struct.pack печатает строку вместо двоичного потока?

var =  struct.pack('hhl3sf', 1, 2, 3, 'm6y', 2.7)
print repr(var)

Вывод:

'\x01\x00\x02\x00\x03\x00\x00\x00m6y\x00\xcd\xcc,@'

Должен ли m6y быть напечатан как \ x6d \ x36 \ x79? И если нет, то как я могу распечатать его прямо из пакета, как она или просто в двоичном виде? И почему char @ print в конце? Спасибо.

Я попытался преобразовать все значения в ascii и затем распечатать их в шестнадцатеричном виде. А также работает binascii.hexlify. Они оба работают, но мне интересно, почему пакет не делает это автоматически. Спасибо.

map(lambda c: ord(c), var)
map(lambda i: hex(i), map(lambda c: ord(c), var))


print 'Packed value : ', binascii.hexlify(var)

Ответы [ 2 ]

1 голос
/ 30 апреля 2019

Представление Python по умолчанию печатает строки байтов в виде символов ascii, где это возможно, и только если \x экранируется, если нет.

Часто ожидается, что 'm6y' будет напечатано как \x6d\x36\x79, но это не так.

Если вы хотите, чтобы переменная отображалась в шестнадцатеричном виде, вам нужно сделать это самостоятельно. Например:

>>> "".join("{0:02x}".format(b) for b in var)
'01000200030000006d367900cdcc2c40'
>>> print("".join("\\0x{0:02x}".format(b) for b in var))
\0x01\0x00\0x02\0x00\0x03\0x00\0x00\0x00\0x6d\0x36\0x79\0x00\0xcd\0xcc\0x2c\0x40

Точно, как вы хотите видеть, зависит от вас. Байт-строки часто являются символами ascii и по умолчанию отображают b"Hello world" как

\0x48\0x65\0x6c\0x6c\0x6f\0x20\0x77\0x6f\0x72\0x6c\0x64

не дружит.

0 голосов
/ 30 апреля 2019

Вопрос о строковой печати

В [SO]: поведение Python struct.pack () (ответ @CristiFati) (где-то в начале), я пытаюсь кратко объяснить поведение. В основном, при отображении некоторого содержимого памяти пользователю, если определенный байт имеет соответствующий печатный символ, этот используется (обратите внимание, что это только для представления , это не влияет на содержимое памяти).
Если вы хотите обойти это поведение, вам придется сделать это вручную (есть несколько способов - я не буду на них настаивать). Но имейте в виду, что при этом результирующая строка не будет эквивалентна исходной :

>>> b0 = b"\x41"
>>> b0
b'A'
>>> len(b0)
1
>>>
>>> b1 = "".join(("\\x{:02X}".format(c) for c in b0))
>>> b1
'\\x41'
>>> len(b1)
4

Окончание символ вопрос

Posting [Python 3.Docs]: struct - интерпретировать байты как упакованные двоичные данные page.

Разбить проблему на более простые и решить каждую из них в отдельности:

  • ' @ ' char ( 0x40 ) в конце полученной строки: это часть представления 2.7 :

    >>> import struct
    >>>
    >>> s0 = struct.pack(b"f", 2.7)
    >>> s0
    b'\xcd\xcc,@'
    >>> len(s0)
    4
    >>>
    >>> s1 = struct.pack(b"f", 1.7)
    >>> s1
    b'\x9a\x99\xd9?'
    >>> len(s1)
    4
    
  • Я полагаю, что путаница была вызвана последним байтом ' \ x00 ' (var[-5]):

    >>> struct.pack(b"3sI", b"ABC", 0xFFFFFFFF)
    b'ABC\x00\xff\xff\xff\xff'
    >>>
    >>> struct.pack(b"@3sI", b"ABC", 0xFFFFFFFF)
    b'ABC\x00\xff\xff\xff\xff'
    >>>
    >>> struct.pack(b"=3sI", b"ABC", 0xFFFFFFFF)
    b'ABC\xff\xff\xff\xff'
    >>>
    >>>
    >>> struct.pack(b"4sI", b"ABCD", 0xFFFFFFFF)
    b'ABCD\xff\xff\xff\xff'
    >>>
    >>> struct.pack(b"1sI", b"A", 0xFFFFFFFF)
    b'A\x00\x00\x00\xff\xff\xff\xff'
    >>>
    >>> struct.pack(b"1sH", b"A", 0xFFFF)
    b'A\x00\xff\xff'
    >>>
    >>> struct.pack(b"1sB", b"A", 0xFF)
    b'A\xff'
    >>>
    >>> struct.pack(b"1sd", b"A", 2.7)
    b'A\x00\x00\x00\x00\x00\x00\x00\x9a\x99\x99\x99\x99\x99\x05@'
    

    Как видно из приведенных выше примеров, не имеет ничего общего с нашим float числом , но со строкой ранее, и это вопрос выравнивания (что для float равно 4 байт). Проверьте [Википедия]: выравнивание структуры данных для получения более подробной информации

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