Apa cara yang benar untuk mengonversi byte ke string hex dengan Python 3?

236

Apa cara yang benar untuk mengonversi byte ke string hex dengan Python 3?

Saya melihat klaim suatu bytes.hexmetode, bytes.decodecodec, dan telah mencoba fungsi lain yang mungkin paling tidak mengejutkan tanpa hasil. Saya hanya ingin byte saya sebagai hex!

Matt Joiner
sumber
"tanpa faedah"? Masalah atau kesalahan spesifik apa yang Anda dapatkan? Tolong tunjukkan kode dan kesalahan.
S.Lott

Jawaban:

410

Sejak Python 3.5 ini akhirnya tidak lagi canggung:

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

dan membalikkan:

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

bekerja juga dengan bytearraytipe yang bisa berubah .

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

Felix Weis
sumber
5
bytes.fromhex()juga tersedia di Python 3.0+ (bukan hanya 3.5+). bytes.hex()hanya di Python 3.5+.
phoenix
95

Gunakan binasciimodul:

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

Lihat jawaban ini: Python 3.1.1 string ke hex

Mu Mind
sumber
8
Ini bagus. Pikiran membingungkan adalah bahwa Anda dapat mengkonversi hex ke byte menggunakan bytes.fromhex (hex_str), tetapi Anda tidak dapat mengkonversi byte ke hex menggunakan bytes.tohex () - apa yang rasional dalam hal ini?
nagylzs
1
Saya kira hubungan antara byte dan hex bukan properti baik (yang tidak menjawab mengapa fromhex ada di sana). Sepertinya itu bukan hanya pengawasan tetapi sesuatu yang diperdebatkan: bugs.python.org/issue3532#msg70950 . T: Apakah akan sakit jika memiliki metode tohex dari objek byte untuk melakukan tugas ini juga? A: IMO, ya, tentu saja. Ini menyulitkan kode, dan menarik fokus dari pendekatan yang tepat untuk konversi data (yaitu, fungsi - bukan metode).
Mu Mind
3
Apakah ini benar-benar menjawab pertanyaan? Itu tidak mengembalikan hex strtetapi a bytes. Saya tahu bahwa OP tampaknya senang dengan jawabannya tetapi tidak akan lebih baik untuk memperluas jawaban ini untuk memasukkan .decode("ascii")juga untuk mengubahnya menjadi "string"
RubenLaguna
3
Saya berpikir bahwa banyak orang mendarat pada pertanyaan / jawaban ini mencari cara untuk mencetak bytes. Jika Anda print(b'666f6f')mendapatkan bhasil cetakannya. Jika Anda .decode("ascii")maka Anda tidak. Hanya memikirkan bagaimana mereka yang benar-benar memiliki bytes(biner sejati dengan item> 128, bukan string ascii) yang ingin mencetaknya.
RubenLaguna
5
@nagylzs: ada .hex()metode dalam Python 3.5+
jfs
43

Python memiliki bytes-to-byte codec standar yang melakukan transformasi nyaman seperti dikutip-printable (cocok untuk 7bits ascii), base64 (cocok dengan alfanumerik), hex escaping, kompresi gzip dan bz2. Dengan Python 2, Anda bisa melakukan:

b'foo'.encode('hex')

Dalam Python 3, str.encode/ bytes.decodesecara ketat untuk byte byte konversi str. Sebagai gantinya, Anda bisa melakukan ini, yang berfungsi melintasi Python 2 dan Python 3 ( s / encode / decode / g untuk kebalikannya):

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

Dimulai dengan Python 3.4, ada opsi yang kurang canggung:

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

Codec misc ini juga dapat diakses di dalam modul mereka sendiri (base64, zlib, bz2, uu, quopri, binascii); API kurang konsisten, tetapi untuk codec kompresi, ia menawarkan lebih banyak kontrol.

Gabriel
sumber
1
menggunakan python 3.3:LookupError: unknown encoding: hex
Janus Troelsen
@ JanusTroelsen: coba 'hex_codec' . Atau cukup gunakan binascii.hexlify(b'foo')langsung
jfs
7
import codecs
codecs.getencoder('hex_codec')(b'foo')[0]

bekerja di Python 3.3 (jadi "hex_codec" bukan "hex").

Richard Kiss
sumber
Mungkin yang menarik, dalam Python 3.4 "hex" atau "hex_codec" berfungsi dengan baik.
Stephen Paulger
6

Metode ini binascii.hexlify()akan dikonversi bytesmenjadi bytesstring hex yang mewakili ascii. Itu berarti bahwa setiap byte dalam input akan dikonversi menjadi dua karakter ascii. Jika Anda ingin yang benar strmaka Anda dapat .decode("ascii")hasilnya.

Saya menyertakan cuplikan yang menggambarkannya.

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

dari string hex "0a160a04"untuk bisa kembali ke bytesdengan binascii.unhexlify("0a160a04")yang memberikan kembalib'\n\x16\n\x04'

RubenLaguna
sumber
3

OK, jawaban berikut sedikit di luar ruang lingkup jika Anda hanya peduli tentang Python 3, tetapi pertanyaan ini adalah hit Google pertama bahkan jika Anda tidak menentukan versi Python, jadi inilah cara yang berfungsi pada Python 2 dan Python 3 .

Saya juga menafsirkan pertanyaan tentang konversi byte ke strtipe: yaitu, byte-y pada Python 2, dan Unicode-y pada Python 3.

Mengingat itu, pendekatan terbaik yang saya tahu adalah:

import six

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

Pernyataan berikut akan berlaku untuk Python 2 atau Python 3, dengan asumsi Anda belum mengaktifkan unicode_literalsmasa depan di Python 2:

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

(Atau Anda dapat menggunakan ''.join()untuk menghilangkan ruang antara byte, dll.)

Peter
sumber
3

dapat digunakan penentu %x02format format dan output nilai hex. Sebagai contoh:

>>> 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
sumber
Menurut saya, ini adalah jawaban terbaik karena berfungsi dengan setiap versi Python dan tidak perlu impor apa pun. Namun, saya lebih baik menampilkan string hexa dalam huruf besarres.upper()
Bruno L.
3

Baru di python 3.8, Anda bisa meneruskan argumen pembatas ke hexfungsi, seperti dalam contoh ini

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

Jika Anda ingin mengonversi b '\ x61' ke 97 atau '0x61', Anda dapat mencoba ini:

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

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

hao li
sumber
Entah bagaimana membantu saya dengan esp32
Tejas Tank