Was ist der richtige Weg, um Bytes in Python 3 in eine Hex-Zeichenfolge zu konvertieren?

235

Was ist der richtige Weg, um Bytes in Python 3 in eine Hex-Zeichenfolge zu konvertieren?

Ich sehe Behauptungen einer bytes.hexMethode, bytes.decodeCodecs, und habe andere mögliche Funktionen des geringsten Erstaunens ohne Erfolg ausprobiert . Ich möchte nur meine Bytes als Hex!

Matt Joiner
quelle
"ohne Erfolg"? Welche spezifischen Probleme oder Fehler treten auf? Bitte zeigen Sie Code und Fehler.
S.Lott

Antworten:

408

Seit Python 3.5 ist dies endlich nicht mehr umständlich:

>>> b'\xde\xad\xbe\xef'.hex()
'deadbeef'

und umgekehrt:

>>> bytes.fromhex('deadbeef')
b'\xde\xad\xbe\xef'

funktioniert auch mit dem veränderlichen bytearrayTyp.

Referenz: https://docs.python.org/3/library/stdtypes.html#bytes.hex

Felix Weis
quelle
5
bytes.fromhex()ist auch für Python 3.0+ verfügbar (nicht nur für 3.5+). bytes.hex()ist nur auf Python 3.5+.
Phoenix
95

Verwenden Sie das binasciiModul:

>>> import binascii
>>> binascii.hexlify('foo'.encode('utf8'))
b'666f6f'
>>> binascii.unhexlify(_).decode('utf8')
'foo'

Siehe diese Antwort: Python 3.1.1 String zu hex

Mu Mind
quelle
8
Das ist gut. Verblüffend ist, dass Sie hexadezimal mit bytes.fromhex (hex_str) in Bytes konvertieren können, aber mit bytes.tohex () keine Bytes in hexadezimal konvertieren können - was ist das Rationale daran?
Nagylzs
1
Ich denke, die Beziehung zwischen Bytes und Hex ist auch keine Eigenschaft von (was nicht antwortet, warum fromhex da ist). Es scheint nicht nur ein Versehen zu sein, sondern etwas, über das gestritten wurde : bugs.python.org/issue3532#msg70950 . F: Würde es weh tun, die Tohex-Methode des Byte-Objekts zu haben, um diese Aufgabe ebenfalls auszuführen? A: IMO, ja, das würde es. Es verkompliziert den Code und lenkt den Fokus von der richtigen Herangehensweise an die Datenkonvertierung ab (nämlich Funktionen - keine Methoden).
Mu Mind
3
Beantwortet dies wirklich die Frage? Es wird kein Hex zurückgegeben, strsondern ein Hexbytes . Ich weiß, dass das OP mit der Antwort zufrieden zu sein scheint, aber es wird nicht besser sein, diese Antwort zu erweitern .decode("ascii"), um sie auch in einen "String"
umzuwandeln
3
Ich dachte, dass viele Leute auf dieser Frage / Antwort landen und nach einer Möglichkeit suchen, a auszudrucken bytes. Wenn Sie print(b'666f6f')das bim Ausdruck bekommen. Wenn Sie .decode("ascii")dann nicht. Ich denke nur daran, wie diejenigen, die tatsächlich eine bytes(echte Binärdatei mit Elementen> 128, keine ASCII-Zeichenfolge) hatten, diese ausdrucken wollten.
RubenLaguna
5
@ Nagylzs: Es gibt .hex()Methode in Python 3.5+
jfs
43

Python verfügt über Standard-Codecs von Byte zu Byte , die bequeme Transformationen ausführen, z. B. in Anführungszeichen druckbar (passt in 7-Bit-ASCII), Base64 (passt in alphanumerische Zeichen), Hex-Escape, Gzip- und BZ2-Komprimierung. In Python 2 können Sie Folgendes tun:

b'foo'.encode('hex')

In Python 3 sind str.encode/ bytes.decodeausschließlich für Bytes <-> str-Konvertierungen. Stattdessen können Sie dies tun, was in Python 2 und Python 3 funktioniert ( s / encode / decode / g für die Umkehrung):

import codecs
codecs.getencoder('hex')(b'foo')[0]

Ab Python 3.4 gibt es eine weniger umständliche Option:

codecs.encode(b'foo', 'hex')

Auf diese verschiedenen Codecs kann auch in ihren eigenen Modulen zugegriffen werden (base64, zlib, bz2, uu, quopri, binascii). Die API ist weniger konsistent, bietet jedoch für Komprimierungscodecs mehr Kontrolle.

Gabriel
quelle
1
mit Python 3.3:LookupError: unknown encoding: hex
Janus Troelsen
@ JanusTroelsen: versuchen Sie 'hex_codec' . Oder verwenden Sie einfach binascii.hexlify(b'foo')direkt
jfs
7
import codecs
codecs.getencoder('hex_codec')(b'foo')[0]

funktioniert in Python 3.3 (also "hex_codec" anstelle von "hex").

Richard Kiss
quelle
Interessanterweise funktioniert in Python 3.4 "hex" oder "hex_codec" einwandfrei.
Stephen Paulger
6

Die Methode binascii.hexlify()konvertiert bytesin eine bytesDarstellung der ASCII-Hex-Zeichenfolge. Das bedeutet, dass jedes Byte in der Eingabe in zwei ASCII-Zeichen konvertiert wird. Wenn Sie ein echtes strOut wollen , dann können Sie .decode("ascii")das Ergebnis.

Ich habe einen Ausschnitt beigefügt, der dies veranschaulicht.

import binascii

with open("addressbook.bin", "rb") as f: # or any binary file like '/bin/ls'
    in_bytes = f.read()
    print(in_bytes) # b'\n\x16\n\x04'
    hex_bytes = binascii.hexlify(in_bytes) 
    print(hex_bytes) # b'0a160a04' which is twice as long as in_bytes
    hex_str = hex_bytes.decode("ascii")
    print(hex_str) # 0a160a04

Von der Hex-Zeichenfolge "0a160a04"bis kann man zu dem zurückkehren, bytesmit binascii.unhexlify("0a160a04")dem man zurückgibtb'\n\x16\n\x04'

RubenLaguna
quelle
3

OK, die folgende Antwort geht etwas über den Rahmen hinaus, wenn Sie sich nur für Python 3 interessieren. Diese Frage ist jedoch der erste Google-Treffer, auch wenn Sie die Python-Version nicht angeben. Hier ist eine Methode, die sowohl für Python 2 als auch für Python 3 funktioniert .

Ich interpretiere die Frage auch so, dass es darum geht, Bytes in den strTyp zu konvertieren : Bytes-y in Python 2 und Unicode-y in Python 3.

Angesichts dessen ist der beste Ansatz, den ich kenne ,:

import six

bytes_to_hex_str = lambda b: ' '.join('%02x' % i for i in six.iterbytes(b))

Die folgende Behauptung gilt entweder für Python 2 oder Python 3, vorausgesetzt, Sie haben die unicode_literalsZukunft in Python 2 nicht aktiviert :

assert bytes_to_hex_str(b'jkl') == '6a 6b 6c'

(Oder Sie können verwenden ''.join(), um den Abstand zwischen den Bytes usw. wegzulassen.)

Peter
quelle
3

Es kann der Formatbezeichner verwendet werden %x02, der einen Hex-Wert formatiert und ausgibt. Beispielsweise:

>>> foo = b"tC\xfc}\x05i\x8d\x86\x05\xa5\xb4\xd3]Vd\x9cZ\x92~'6"
>>> res = ""
>>> for b in foo:
...     res += "%02x" % b
... 
>>> print(res)
7443fc7d05698d8605a5b4d35d56649c5a927e2736
Arg0s
quelle
Meiner Meinung nach ist es die beste Antwort, da es mit jeder Python-Version funktioniert und keinen Import benötigt. Ich würde jedoch besser Hexa-Zeichenfolgen in Großbuchstaben anzeigenres.upper()
Bruno L.
3

Neu in Python 3.8 können Sie hexwie in diesem Beispiel ein Trennzeichenargument an die Funktion übergeben

>>> value = b'\xf0\xf1\xf2'
>>> value.hex('-')
'f0-f1-f2'
>>> value.hex('_', 2)
'f0_f1f2'
>>> b'UUDDLRLRAB'.hex(' ', -4)
'55554444 4c524c52 4142'

https://docs.python.org/3/library/stdtypes.html#bytes.hex

Peter Mitrano
quelle
0

Wenn Sie b '\ x61' in 97 oder '0x61' konvertieren möchten, können Sie Folgendes versuchen:

[python3.5]
>>>from struct import *
>>>temp=unpack('B',b'\x61')[0] ## convert bytes to unsigned int
97
>>>hex(temp) ##convert int to string which is hexadecimal expression
'0x61'

Referenz: https://docs.python.org/3.5/library/struct.html

hao li
quelle
Hilft mir irgendwie mit esp32
Tejas Tank