2008-12-22 12 views
6

Ich versuche, mit einem Gerät mit Python zu sprechen. Mir wurde ein Tupel von Bytes übergeben, das die Speicherinformation enthält. Wie kann ich die Daten in die richtigen Werte zu konvertieren:Wie konvertiere ich einen Teil eines Python-Tupels (Byte-Array) in eine ganze Zahl

response = (0, 0, 117, 143, 6)

Die ersten 4 Werte sind ein 32-Bit-int mir zu sagen, wie viele Bytes verwendet wurden, und der letzte Wert ist der verwendete Prozentsatz.

Ich kann auf das Tupel als Antwort [0] zugreifen, kann aber nicht sehen, wie ich die ersten 4 Werte in den int bekomme, den ich benötige.

Antwort

11

Siehe Convert Bytes to Floating Point Numbers in Python

Sie wahrscheinlich die Struktur-Modul verwenden möchten, zum Beispiel

import struct 

response = (0, 0, 117, 143, 6) 
struct.unpack(">I", ''.join([chr(x) for x in response[:-1]])) 

Angenommen, ein int. Es könnte einen besseren Weg geben, die Konvertierung zum Entpacken durchzuführen, ein Listenverständnis mit Join war nur das erste, was mir einfiel.

EDIT: Siehe auch ΤΖΩΤΖΙΟΥs Kommentar zu dieser Antwort bezüglich Endianness.

EDIT # 2: Wenn es Ihnen nichts ausmacht, das Array-Modul auch zu verwenden, ist hier eine alternative Methode, die die Notwendigkeit für ein Listenverständnis beseitigt. Danke an @JimB für den Hinweis, dass das Entpacken auch auf Arrays funktionieren kann.

import struct 
from array import array 

response = (0, 0, 117, 143, 6) 
bytes = array('B', response[:-1]) 
struct.unpack('>I', bytes) 
+1

Ich würde vorschlagen, dass das Packformat "> I", d. H. Big Endian; 0x0000758f (30095₁₀) für eine zufällige Anzahl von Bytes scheint wahrscheinlicher als 0x8f750000 (2406809600₁₀) – tzot

13

Würde,

num = (response [0] < < 24) + (Reaktion [1] < < 16) + (Reaktion [2] < < 8) + Antwort [3]

erfüllen Sie Ihre Bedürfnisse?

Hilfe

+2

beim Lesen der obigen Antworten mit dem Importieren von Modulen, mit Loops und Comprehensions für etwas so trivial wie das, fing ich wirklich an meinen Kopf kratzen ... diese Antwort ist eigentlich wie es ist (und sollte) überall gemacht werden, und nichts wird dies in Bezug auf Geschwindigkeit und Einfachheit schlagen ... – Tom

+0

Ein einfacher Weg, es zu tun – user2578666

4

OK, Sie geben nicht die endinanness oder ob die ganze Zahl ist unterschrieben oder es (vielleicht) ist schneller mit der Struktur-Modul aber:

b = (8, 1, 0, 0) 
sum(b[i] << (i * 8) for i in range(4)) 
+0

nur als Referenz ist dies für Little-Endian und kann möglicherweise leicht verbessert werden als 'sum (b [i] << (i * 8) für i im Bereich (len (b)))', um Eingaben variabler Größe oder 'Summe (Antwort [i] << (i * 8) für i im Bereich (len (Antwort) -1)) 'für das OP. – Caltor

+0

@Ad__ Ich mag diese Lösung, da sie wahrscheinlich schneller als struct.unpack ist und im Gegensatz zu dieser Methode kein Modul importiert werden muss. Könnten Sie bitte eine Version liefern, die mit Big-Endian umgehen würde? – Caltor

4

Sie auch machen könnte Verwendung der Array-Modul

import struct 
from array import array 
response = (0, 0, 117, 143, 6) 
a = array('B', response[:4]) 
struct.unpack('>I', a) 

(30095L,) 
+0

Ich habe diesen Ansatz auch ausprobiert, aber ich entschied mich dafür, mit einem Listenverständnis zu gehen und stattdessen() zu verbinden, um zu vermeiden, ein anderes Modul zu importieren, und da beides leider nicht besonders klar war. – Jay

+0

Ich habe vergessen, dass struct Packs [feste Antwort] pack, was ich denke, macht diese Version etwas besser als die Liste comp. – JimB

+0

Schön, ich wusste nicht, dass es das tun könnte, verpasst das in der Dokumentation. Ich werde es meiner Antwort auch als Alternative hinzufügen. – Jay

0

Wie über die Karte Funktion:

a = (0, 0, 117, 143, 6) 
b = [] 
map(b.append, a) 

Auch ich weiß nicht, ob dies der Sie suchen:

response = (0, 0, 117, 143, 6) 
response[0:4] 
3

Dieses wie ein Job sucht zu reduzieren!

Was Sie im Grunde brauchen, ist, Bit-Shift ein Byte nach dem anderen, und dann hinzufügen (Addition) das nächste Byte in der Sequenz.

a = (0, 0, 117, 143, 6) 
reduce(lambda x, y: (x<<8) + y, a) 
7704326 
+0

-1 Lesen Sie die Frage. Es gibt fünf Bytes. Das OP sagt, die ersten 4 sind ein 32-Bit-Int. Der letzte ist ein Prozentsatz (6%). –

+0

@John: Ich denke, es ist nur ein kleiner Fehler, ändere einfach in der zweiten Zeile '' a'' in '' a [: 4] '' und der Code funktioniert wie vom OP benötigt (zumindest wenn Big Endian gemeint ist). Sie müssen das nicht direkt ablehnen. –

+0

@Kristian eine Chance auf eine Version von diesem für Little Endian bitte? – Caltor

Verwandte Themen