Jaki jest prawidłowy sposób konwersji bajtów na ciąg szesnastkowy w Pythonie 3?
Widzę roszczenia do bytes.hexmetody, bytes.decodekodekó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.hexmetody, bytes.decodekodekó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 bytearraytypem 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 binasciimoduł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ę
strale 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 bna 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.decodesą 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 bytesna bytesreprezentują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 bytesz 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 strtyp: 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_literalsprzyszł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, %x02któ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 hexfunkcji 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