2011-05-31 13 views
20

Necesito enviar un mensaje de bytes en Python y necesito convertir un número entero sin signo en una matriz de bytes. ¿Cómo se convierte un valor entero en una matriz de cuatro bytes en Python? Como en C:Cómo convertir valores enteros en una matriz de cuatro bytes en python

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

¿Alguien me puede mostrar cómo? Al principio me resulta extraño programar sin tipos.

Respuesta

11

Sven tiene su respuesta. Sin embargo, los números de bytes de cambio (como en su pregunta) también es posible en Python:

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

Eche un vistazo al módulo struct. Probablemente todo lo que necesita es struct.pack("I", your_int) para empaquetar el número entero en una cadena, y luego coloque esta cadena en el mensaje. La cadena de formato "I" denota un entero de 32 bits sin signo.

Si se desea expandir una cadena de este tipo a una tupla de los enteros, puede utilizar struct.unpack("4b", s):

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

(El ejemplo es, obviamente, en una máquina ascendente hacia la izquierda.)

+6

Dependiendo de la máquina en la que se ejecute este código, el orden de bytes del host probablemente no es el que desea. Utilice "! I" para serializar un int sin firmar a la red byteorder. – dantje

4

Puede más o menos lo mismo:

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

o puede hacer algo más corto:

>>> array = [(number>>(8*i))&0xff for i in range(3,-1,-1)] 
7

En caso de que alguien mira a esta pregunta en algún momento después ...
Esta declaración debe ser equivalente al código en la pregunta original :

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

Y no creo que importe el orden de bytes del host.
Si sus enteros son más grandes que int32, puede usar "!Q" en la llamada a pack() para int64 (si su sistema admite Q).
Y list() o incluso bytearray() funcionará en lugar de tuple().

Nota: el resultado es una secuencia de objetos str (cada uno con un solo byte), no enteros. Si usted debe tener una lista de números enteros, se puede hacer esto:

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

... o esto:

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

Pero el uso de map() comienza a hacer las cosas un poco desordenado.

7

esto es una especie de un viejo hilo, pero en Python 3.2+ ahora usted puede simplemente decir:

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

o byteorder = 'little' según sus necesidades. Documentación here.

0

está completo y si: también puede utilizar el módulo de 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' 
0

Se puede hacer con ctypes también. Es especialmente útil para convertir números de coma flotante en bytes. Ejemplo:

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