Как преобразовать целочисленное значение в массив из четырех байтов в Python - PullRequest
23 голосов
/ 31 мая 2011

Мне нужно отправить сообщение байтов в Python, и мне нужно преобразовать целое число без знака в байтовый массив.Как преобразовать целочисленное значение в массив из четырех байтов в Python?Как в C:

uint32_t number=100;
array[0]=(number >>24) & 0xff;
array[1]=(number >>16) & 0xff;
array[2]=(number >>8) & 0xff;
array[3]=number & 0xff;

Может кто-нибудь показать мне, как?Мне странно сначала программировать без типов.

Ответы [ 7 ]

32 голосов
/ 31 мая 2011

Посмотрите на модуль struct.Вероятно, все, что вам нужно, это struct.pack("I", your_int), чтобы упаковать целое число в строку, а затем поместить эту строку в сообщение.Строка формата "I" обозначает 32-разрядное целое число без знака.

Если вы хотите распаковать такую ​​строку в кортеж целых чисел, вы можете использовать struct.unpack("4b", s):

>>> struct.unpack("4b", struct.pack("I", 100))
(100, 0, 0, 0)

(Пример явно на машине с прямым порядком байтов.)

15 голосов
/ 06 декабря 2016

Это своего рода старая тема, но в Python 3.2+ теперь вы можете просто сказать:

number = 100
number.to_bytes(4, byteorder = 'big')

или byteorder = 'little' в соответствии с вашими потребностями.Документация здесь .

14 голосов
/ 31 мая 2011

Свен ответили. Тем не менее, в Python также возможно изменение числа байтов (как в вашем вопросе):

>>> [hex(0x12345678 >> i & 0xff) for i in (24,16,8,0)]
['0x12', '0x34', '0x56', '0x78']
7 голосов
/ 08 февраля 2012

На случай, если кто-нибудь посмотрит на этот вопрос позже ...
Это утверждение должно быть эквивалентно коду в исходном вопросе:

>>> tuple( struct.pack("!I", number) )
('\x00', '\x00', '\x00', 'd')

И я не думаю, что это имеет значениеПорядок байтов хоста:
Если ваши целые числа больше, чем int32, вы можете использовать "!Q" в вызове pack() для int64 (если ваша система поддерживает Q).
И list() или дажеbytearray() будет работать вместо tuple().

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

[ ord(c) for c in struct.pack("!I", number) ]
[0, 0, 0, 100]

... или это:

>>> map( ord, tuple( struct.pack("!I", number) ) )
[0, 0, 0, 100]

Но использование map() приводит к некоторому беспорядку.

4 голосов
/ 31 мая 2011

Вы можете сделать то же самое:

>>> number = 100
>>> array[0] = (number>>24) & 0xff
>>> array[1] = (number>>16) & 0xff
>>> array[2] = (number>>8) & 0xff
>>> array[3] = number & 0xff

или сделать что-то более короткое:

>>> array = [(number>>(8*i))&0xff for i in range(3,-1,-1)]
1 голос
/ 27 ноября 2017

Это также можно сделать с помощью ctypes.Это особенно полезно для преобразования чисел с плавающей запятой в байты.Пример:

>>> bytes(ctypes.c_uint32(0x20))
b' \x00\x00\x00'
>>> bytes(ctypes.c_double(1))
b'\x00\x00\x00\x00\x00\x00\xf0?'
0 голосов
/ 30 июня 2017

А для полноты: вы также можете использовать модуль array:

>>> from array import array
>>> a = array('I', [100]) # note that 'I' and such are machine-dependent.
>>> a.tostring()
'\d\x00\x00\x00'
>>> a.byteswap()
>>> a.tostring()
'\x00\x00\x00\d'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...