Jaki jest prawidłowy sposób konwersji bajtów na ciąg szesnastkowy w Pythonie 3?
Widzę roszczenia do bytes.hex
metody, bytes.decode
kodeków i wypróbowałem inne możliwe funkcje najmniejszego zdziwienia bezskutecznie. Chcę tylko moje bajty jako hex!
Jaki jest prawidłowy sposób konwersji bajtów na ciąg szesnastkowy w Pythonie 3?
Widzę roszczenia do bytes.hex
metody, bytes.decode
kodeków i wypróbowałem inne możliwe funkcje najmniejszego zdziwienia bezskutecznie. Chcę tylko moje bajty jako hex!
Odpowiedzi:
Od wersji Python 3.5 nie jest to już niewygodne:
>>> b'\xde\xad\xbe\xef'.hex()
'deadbeef'
i odwróć:
>>> bytes.fromhex('deadbeef')
b'\xde\xad\xbe\xef'
działa również z bytearray
typem zmiennym .
Odniesienie: https://docs.python.org/3/library/stdtypes.html#bytes.hex
bytes.fromhex()
jest również dostępny w Python 3.0+ (nie tylko 3.5+). bytes.hex()
jest tylko w Python 3.5+.
Użyj binascii
modułu:
>>> import binascii
>>> binascii.hexlify('foo'.encode('utf8'))
b'666f6f'
>>> binascii.unhexlify(_).decode('utf8')
'foo'
Zobacz następującą odpowiedź: Ciąg w Pythonie 3.1.1 na szesnastkę
str
ale bytes
. Wiem, że OP wydaje się być zadowolony z odpowiedzi, ale nie będzie lepiej rozszerzyć tę odpowiedź, aby objąć .decode("ascii")
ją również „ciągiem”
bytes
. Jeśli print(b'666f6f')
dostaniesz b
na wydruku. Jeśli nie .decode("ascii")
, to nie. Wystarczy pomyśleć o tym, jak ci, którzy faktycznie mieli bytes
(prawdziwy plik binarny z elementami> 128, a nie ciąg ascii), chcieli go wydrukować.
.hex()
w Python 3.5+ istnieje metoda
Python ma standardowe kodeki bajt-bajt, które wykonują wygodne transformacje, takie jak drukowanie w cudzysłowie (pasuje do 7-bitowych znaków ascii), base64 (pasuje do znaków alfanumerycznych), ucieczkę szesnastkową, kompresję gzip i bz2. W Pythonie 2 możesz wykonać:
b'foo'.encode('hex')
W Pythonie 3, str.encode
/ bytes.decode
są przeznaczone wyłącznie do konwersji bajtów <-> str. Zamiast tego możesz to zrobić, co działa w Pythonie 2 i Pythonie 3 ( s / encode / decode / g dla odwrotności):
import codecs
codecs.getencoder('hex')(b'foo')[0]
Począwszy od Python 3.4, jest mniej niewygodna opcja:
codecs.encode(b'foo', 'hex')
Te różne kodeki są również dostępne we własnych modułach (base64, zlib, bz2, uu, quopri, binascii); interfejs API jest mniej spójny, ale w przypadku kodeków kompresji oferuje większą kontrolę.
LookupError: unknown encoding: hex
binascii.hexlify(b'foo')
bezpośrednio
import codecs
codecs.getencoder('hex_codec')(b'foo')[0]
działa w Pythonie 3.3 (więc „hex_codec” zamiast „hex”).
Metoda binascii.hexlify()
zostanie przekonwertowana bytes
na bytes
reprezentujący ciąg szesnastkowy ascii. Oznacza to, że każdy bajt na wejściu zostanie przekonwertowany na dwa znaki ascii. Jeśli chcesz się spełnić str
, możesz uzyskać .decode("ascii")
wynik.
Dołączyłem fragment, który to ilustruje.
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
z ciągiem szesnastkowym "0a160a04"
, aby można wrócić do bytes
z binascii.unhexlify("0a160a04")
której oddajeb'\n\x16\n\x04'
OK, poniższa odpowiedź jest nieco poza zakresem, jeśli dbasz tylko o Python 3, ale to pytanie jest pierwszym hitem Google, nawet jeśli nie określisz wersji Python, więc oto sposób, który działa zarówno na Python 2, jak i Python 3 .
Interpretuję również pytanie o konwersję bajtów na str
typ: to znaczy bajty-y w Pythonie 2 i Unicode-y w Pythonie 3.
Biorąc to pod uwagę, najlepszym znanym mi podejściem jest:
import six
bytes_to_hex_str = lambda b: ' '.join('%02x' % i for i in six.iterbytes(b))
Poniższe stwierdzenie będzie prawdziwe dla Pythona 2 lub Pythona 3, zakładając, że nie aktywowałeś unicode_literals
przyszłości w Pythonie 2:
assert bytes_to_hex_str(b'jkl') == '6a 6b 6c'
(Lub możesz użyć, ''.join()
aby pominąć spację między bajtami itp.)
można użyć specyfikatora formatu, %x02
który formatuje i generuje wartość szesnastkową. Na przykład:
>>> 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
res.upper()
Nowość w Pythonie 3.8, możesz przekazać argument hex
funkcji ogranicznika, tak jak w tym przykładzie
>>> value = b'\xf0\xf1\xf2'
>>> value.hex('-')
'f0-f1-f2'
>>> value.hex('_', 2)
'f0_f1f2'
>>> b'UUDDLRLRAB'.hex(' ', -4)
'55554444 4c524c52 4142'
Jeśli chcesz przekonwertować b '\ x61' na 97 lub „0x61”, możesz spróbować:
[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'
Odniesienie: https://docs.python.org/3.5/library/struct.html