Каков правильный способ преобразования байтов в шестнадцатеричную строку в Python 3?

Как правильно преобразовать байты в шестнадцатеричную строку в Python 3?

Я вижу претензии bytes.hex метод bytes.decode кодеки и пробовал другое возможные функции наименьшего удивления безрезультатно. Я просто хочу, чтобы мои байты были hex!

8 ответов


С Python 3.5 это, наконец, больше не неудобно:

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

и обратное:

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

работает также с изменяемым bytearray тип.


использовать binascii модуль:

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

посмотреть этот ответ: Python 3.1.1 строка в hex


Python имеет байт-в-байт стандартные кодеки которые выполняют удобные преобразования, такие как quoted-printable (вписывается в 7bits ascii), base64 (вписывается в алфавитно-цифровые символы), шестнадцатеричное экранирование, сжатие gzip и bz2. В Python 2 Вы можете сделать:

b'foo'.encode('hex')

В Python 3, str.encode / bytes.decode строго для байтов преобразования str. Вместо этого, вы можете сделать это, который работает на Python 2 и Python 3 (s / encode/decode / g для обратный):

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

начиная с Python 3.4, есть менее неудобный вариант:

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

эти разные кодеки также доступны внутри их собственных модулей (base64, zlib, bz2, uu, quopri, binascii); API менее последователен, но для кодеков сжатия он предлагает больше контроля.


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

работает в Python 3.3 (поэтому "hex_codec" вместо "hex").


метод binascii.hexlify() преобразует bytes до bytes представление шестнадцатеричной строки ascii. Это означает, что каждый байт на входе будет преобразован в два символа ascii. Если вы хотите true str вы можете .decode("ascii") результат.

я включил фрагмент, который иллюстрирует это.

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

из шестнадцатеричной строки "0a160a04" чтобы можно было вернуться к bytes С binascii.unhexlify("0a160a04"), который возвращает b'\n\x16\n\x04'


хорошо, следующий ответ немного выходит за рамки, если вы заботитесь только о Python 3, но этот вопрос является первым хитом Google, даже если вы не указываете версию Python, так что вот способ, который работает на обоих Python 2 и Python 3.

Я также интерпретирую вопрос о преобразовании байтов в str тип: то есть байты-y на Python 2 и Unicode-y на Python 3.

учитывая это, лучший подход, который я знаю есть:

import six

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

следующее утверждение будет истинным для Python 2 или Python 3, Если вы не активировали unicode_literals будущее в Python 2:

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

(или вы можете использовать ''.join() чтобы опустить пространство между байтами и т. д.)


можно использовать спецификатор формата %x02 этот формат и вывод шестнадцатеричного значения. Например:

>>> 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

Если вы хотите преобразовать b '\x61 'в 97 или '0x61', вы можете попробовать следующее:

[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'

Ссылка:https://docs.python.org/3.5/library/struct.html