Подтвердить что ты не робот

Как преобразовать целочисленное значение в массив из четырех байтов в python

Мне нужно отправить сообщение байтов в 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;

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

4b9b3361

Ответ 1

Свен отвечает. Однако в Python также возможны числа смещения байтов (как и в вашем вопросе):

>>> [hex(0x12345678 >> i & 0xff) for i in (24,16,8,0)]
['0x12', '0x34', '0x56', '0x78']

Ответ 2

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

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

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

(Пример, очевидно, на машине маленького конца.)

Ответ 3

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

>>> 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

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

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

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

Ответ 5

Вы можете в значительной степени сделать то же самое:

>>> 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)]

Ответ 6

И для полноты: вы также можете использовать модуль 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'

Ответ 7

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

>>> bytes(ctypes.c_uint32(0x20))
b' \x00\x00\x00'
>>> bytes(ctypes.c_double(1))
b'\x00\x00\x00\x00\x00\x00\xf0?'