Как распаковать 6 байтов как одно целое, используя struct в Python - PullRequest
7 голосов
/ 31 октября 2011

У меня есть следующие 8 байтов:

b'\x05\x00\x00\x00\x00\x00\x05\x00'

Я пытаюсь получить два целых числа, используя struct.unpack: одно для первых 2 байтов и одно для последних 6. Получить первые два легко, используя:

struct.unpack("<H6B")

Но это возвращает

(5, 0, 0, 0, 0, 5, 0)

Я хочу вернуть следующее:

(5, 5)

Как получить целочисленное значение последних 6 байтов? Я не хочу каждый байт индивидуально.

Ответы [ 2 ]

11 голосов
/ 31 октября 2011

struct не поддерживает целые числа с размером не степени двух. Это распространено. C также не поддерживает такие целые числа на вашей платформе (ну, битовые поля, но вы не можете создать их массив).

def unpack48(x):
    x1, x2, x3 = struct.unpack('<HHI', x)
    return x1, x2 | (x3 << 16)
4 голосов
/ 31 октября 2011

Стандартный модуль структуры не поддерживает все возможные размеры, поэтому вы должны либо самостоятельно соединить несколько битов (см. Ответ Дитриха), либо использовать внешние модули, такие как цепочка битов .

>>> from bitstring import BitArray
>>> b = BitArray(bytes=b'\x05\x00\x00\x00\x00\x00\x05\x00')
>>> b.unpack('<H6B')
[5, 0, 0, 0, 0, 5, 0]

, что соответствует стандарту struct.unpack. Но теперь мы можем вместо этого распаковать второй элемент как 6-байтовое (48-битное) целое число без знака с прямым порядком байтов:

>>> b.unpack('<H, uintle:48')
[5, 21474836480]                   

, который дает вам тот же результат, что и ответ Дитриха, а также показывает, что вы ошиблись в своем вопросе! Что вам нужно в этом случае:

>>> b.unpack('uintle:48, <H')
[5, 5]

Обратите внимание, что вы также можете написать <H как uintle:16, если хотите более последовательную запись.

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