Wie kann ich eine Byte-Zeichenfolge in Python in ein Int konvertieren?
Sagen Sie so: 'y\xcc\xa6\xbb'
Ich habe mir eine clevere / dumme Methode ausgedacht:
sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))
Ich weiß, dass es etwas Eingebautes oder in der Standardbibliothek geben muss, das dies einfacher macht ...
Dies unterscheidet sich von der Konvertierung einer Zeichenfolge mit Hex-Ziffern, für die Sie int (xxx, 16) verwenden können. Stattdessen möchte ich eine Zeichenfolge mit tatsächlichen Bytewerten konvertieren.
AKTUALISIEREN:
Ich mag James 'Antwort ein bisschen besser, weil es nicht erforderlich ist, ein anderes Modul zu importieren, aber Gregs Methode ist schneller:
>>> from timeit import Timer
>>> Timer('struct.unpack("<L", "y\xcc\xa6\xbb")[0]', 'import struct').timeit()
0.36242198944091797
>>> Timer("int('y\xcc\xa6\xbb'.encode('hex'), 16)").timeit()
1.1432669162750244
Meine hackige Methode:
>>> Timer("sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))").timeit()
2.8819329738616943
WEITERES UPDATE:
Jemand fragte in Kommentaren, was das Problem beim Importieren eines anderen Moduls sei. Der Import eines Moduls ist nicht unbedingt billig.
>>> Timer("""import struct\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""").timeit()
0.98822188377380371
Durch die Einbeziehung der Kosten für den Import des Moduls wird fast der gesamte Vorteil dieser Methode zunichte gemacht. Ich glaube, dass dies nur die Kosten für den einmaligen Import für den gesamten Benchmark-Lauf beinhaltet. Schauen Sie, was passiert, wenn ich es jedes Mal zum Neuladen zwinge:
>>> Timer("""reload(struct)\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""", 'import struct').timeit()
68.474128007888794
Es ist unnötig zu erwähnen, dass, wenn Sie viele Ausführungen dieser Methode pro Import durchführen, dies proportional weniger problematisch wird. Es ist wahrscheinlich auch eher E / A-Kosten als CPU, so dass es von der Kapazität und den Lasteigenschaften der jeweiligen Maschine abhängen kann.
int.from_bytes
) der mechanischen Schnecke wurdestruct.unpack
auf meinem Computer übertroffen . Neben besser lesbar imo.Antworten:
Sie können dazu auch das struct- Modul verwenden:
quelle
Verwenden Sie in Python 3.2 und höher
oder
entsprechend der Endianness Ihres Byte-Strings.
Dies funktioniert auch für Bytestring-Ganzzahlen beliebiger Länge und für Zwei-Komplement-Ganzzahlen mit Vorzeichen durch Angabe
signed=True
. Siehe die Dokumente fürfrom_bytes
.quelle
os.urandom(4)
Bytes ** 1,4 µs ** (struct) vs ** 2,3 µs ** (int.from_bytes) auf meiner CPU. Python 3.5.2Wie Greg sagte, können Sie struct verwenden, wenn Sie mit Binärwerten arbeiten, aber wenn Sie nur eine "Hex-Zahl" haben, aber im Byte-Format, möchten Sie sie vielleicht einfach wie folgt konvertieren:
... das ist das gleiche wie:
... außer es funktioniert für eine beliebige Anzahl von Bytes.
quelle
int(''.join(reversed(s)).encode('hex'), 16)
Ich benutze die folgende Funktion, um Daten zwischen int, hex und Bytes zu konvertieren.
Quelle: http://opentechnotes.blogspot.com.au/2014/04/convert-values-to-from-integer-hex.html
quelle
Warnung: Das oben Genannte ist stark plattformspezifisch. Sowohl der "I" -Spezifizierer als auch die Endianness der string-> int-Konvertierung hängen von Ihrer speziellen Python-Implementierung ab. Wenn Sie jedoch viele Ganzzahlen / Zeichenfolgen gleichzeitig konvertieren möchten, erledigt das Array-Modul dies schnell.
quelle
In Python 2.x können Sie die Formatbezeichner
<B
für vorzeichenlose Bytes und<b
für vorzeichenbehaftete Bytes mitstruct.unpack
/ verwendenstruct.pack
.Z.B:
Sei
x
='\xff\x10\x11'
Und:
Das
*
ist erforderlich!Sehen https://docs.python.org/2/library/struct.html#format-characters für eine Liste der Formatspezifizierer.
quelle
Test 1: invers:
Test 2: Anzahl der Bytes> 8:
Test 3: Inkrement um eins:
Test 4: Fügen Sie ein Byte hinzu und sagen Sie 'A':
Test 5: Teilen durch 256:
Das Ergebnis entspricht erwartungsgemäß dem Ergebnis von Test 4.
quelle
Ich hatte Mühe, eine Lösung für Byte-Sequenzen beliebiger Länge zu finden, die unter Python 2.x funktionieren würden. Schließlich habe ich dieses geschrieben, es ist ein bisschen hacky, weil es eine String-Konvertierung durchführt, aber es funktioniert.
Funktion für Python 2.x, beliebige Länge
Diese Funktion hat zwei Anforderungen:
Die Eingabe
data
muss a seinbytearray
. Sie können die Funktion folgendermaßen aufrufen:Die Daten müssen Big-Endian sein. Wenn Sie einen Little-Endian-Wert haben, sollten Sie ihn zuerst umkehren:
Dies sollte natürlich nur verwendet werden, wenn eine beliebige Länge benötigt wird. Ansonsten bleiben Sie bei den Standardmethoden (z
struct
. B. ).quelle
int.from_bytes ist die beste Lösung, wenn Sie Version> = 3.2 verwenden. Die "struct.unpack" -Lösung erfordert eine Zeichenfolge, sodass sie nicht für Arrays von Bytes gilt. Hier ist eine andere Lösung:
hex (bytes2int ([0x87, 0x65, 0x43, 0x21])) gibt '0x87654321' zurück.
Es verarbeitet große und kleine Endianness und kann leicht für 8 Bytes geändert werden
quelle
Wie oben erwähnt, ist die Verwendung der
unpack
Funktion struct ein guter Weg. Wenn Sie Ihre eigene Funktion implementieren möchten, gibt es eine andere Lösung:quelle
In Python 3 können Sie eine Byte-Zeichenfolge einfach in eine Liste von Ganzzahlen (0..255) konvertieren
quelle
Eine anständig schnelle Methode mit array.array, die ich seit einiger Zeit verwende:
vordefinierte Variablen:
zu int: (lesen)
von int: (schreiben)
Es ist jedoch möglich, dass diese schneller sind.
BEARBEITEN:
Für einige Zahlen ist hier ein Leistungstest (Anaconda 2.3.0), der stabile Durchschnittswerte beim Lesen im Vergleich zu
reduce()
: zeigt.Dies ist ein roher Leistungstest, daher wird der Endian-Pow-Flip weggelassen.
Die
shift
gezeigte Funktion wendet dieselbe Verschiebungsoperation wie die for-Schleife an undarr
ist genau so,array.array('B',[0,0,255,0])
wie sie nebenan die schnellste iterative Leistung aufweistdict
.Ich sollte wahrscheinlich auch beachten, dass die Effizienz an der Genauigkeit der Durchschnittszeit gemessen wird.
quelle