2011-05-31 18 views
20

Potrzebuję wysłać wiadomość o bajtach w Pythonie i potrzebuję przekonwertować liczbę całkowitą bez znaku na tablicę bajtów. Jak przekonwertować wartość całkowitą do tablicy czterech bajtów w Pythonie? Podobnie jak w C:Jak przekonwertować liczbę całkowitą na tablicę czterech bajtów w pythonie

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

Czy ktoś może mi pokazać? Dziwnie jest mi początkowo programować bez typów.

Odpowiedz

11

Sven odpowiedziałeś. Jednak bajt przesunięcie numerów (jak w pytaniu) jest również możliwe w Pythonie:

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

Spójrz na moduł struct. Prawdopodobnie potrzebujesz tylko struct.pack("I", your_int), aby spakować liczbę całkowitą w ciągu znaków, a następnie umieścić ten ciąg w wiadomości. Łańcuch formatu "I" oznacza niepodpisaną 32-bitową liczbę całkowitą.

Jeśli chcesz rozpakować taki ciąg krotką dla liczb całkowitych, można użyć struct.unpack("4b", s):

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

(Przykład jest oczywiście na ostrokońcej maszynie.)

+6

W zależności od urządzenia, na którym działa ten kod, kolejność bajtów hosta prawdopodobnie nie jest tym, czego potrzebujesz. Użyj "! I", aby serializować niepodpisane int do bajtów sieciowych. – dantje

4

Można dość dużo zrobić to samo:

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

czy można zrobić coś krótszego:

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

W przypadku gdy ktoś patrzy na to pytanie jakiś czas później ...
Oświadczenie to powinno być równoważne do kodu w oryginalnym pytanie :

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

I nie sądzę, aby miało znaczenie to, co jest porządkiem bajtów hosta.
Jeśli twoje liczby całkowite są większe niż int32, możesz użyć "!Q" w wywołaniu pack() dla int64 (jeśli twój system obsługuje Q).
i list() lub nawet bytearray() będzie działać zamiast tuple().

Uwaga: wynikiem jest sekwencja obiektów str (każdy zawiera pojedynczy bajt), a nie liczby całkowite. Jeśli musisz mieć listę liczb całkowitych, można to zrobić:

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

... albo to:

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

Ale używając map() zaczyna produkować rzeczy nieco niechlujnie.

7

Jest to rodzaj starego wątku, ale w Pythonie 3.2 lub nowszym teraz można po prostu powiedzieć:

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

lub byteorder = 'little' jak na swoje potrzeby. Dokumentacja here.

0

A dla kompletności: można również użyć modułu 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

można to zrobić z ctypes również. Jest to szczególnie przydatne przy przekształcaniu liczb zmiennoprzecinkowych na bajty. Przykład:

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