2011-05-31 9 views
20

Ho bisogno di inviare un messaggio di byte in Python e ho bisogno di convertire un numero intero senza segno in un array di byte. Come si converte un valore intero in una matrice di quattro byte in Python? Come in C:Come convertire il valore intero in array di quattro byte in python

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

Qualcuno può mostrarmi come? È strano per me, in un primo momento, programmare senza tipi.

risposta

11

Sven ha una risposta. Tuttavia, byte numeri spostamento (come nella tua domanda) è possibile anche in Python:

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

Dai un'occhiata al modulo struct. Probabilmente tutto ciò che serve è struct.pack("I", your_int) per impacchettare il numero intero in una stringa, quindi inserire questa stringa nel messaggio. La stringa di formato "I" denota un numero intero a 32 bit senza segno.

Se si desidera decomprimere tale stringa in una tupla di per gli interi, è possibile utilizzare struct.unpack("4b", s):

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

(L'esempio è ovviamente su una macchina little-endian.)

+6

A seconda della macchina su cui viene eseguito questo codice, l'ordine dei byte host probabilmente non è quello che si desidera. Utilizzare "! I" per serializzare un int unsigned in byteorder di rete. – dantje

4

Puoi più o meno la stessa cosa:

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

o si può fare qualcosa di più breve:

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

Nel caso qualcuno guarda a questa domanda qualche tempo dopo ...
Questa affermazione dovrebbe essere equivalente al codice nella domanda originale :

E non penso che importi l'ordine dei byte host.
Se i numeri interi sono maggiori di int32, è possibile utilizzare "!Q" nella chiamata a pack() per int64 (se il sistema supporta Q).
E list() o anche bytearray() funzionerà al posto di tuple().

Nota: il risultato è una sequenza di oggetti str (ognuno con un singolo byte), non numeri interi. Se è necessario disporre di un elenco di numeri interi, si può fare questo:

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

... o questo:

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

Ma usando map() inizia a fare le cose un po 'disordinato.

7

questo è una specie di un vecchio thread, ma in Python 3.2 + Ora si può semplicemente dire:

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

o byteorder = 'little' secondo i vostri bisogni. Documentazione here.

0

E per completezza: è anche possibile utilizzare il modulo 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

Può essere fatto con ctypes pure. È particolarmente utile per convertire i numeri in virgola mobile in byte. Esempio:

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