Cách chính xác để chuyển đổi byte thành chuỗi hex trong Python 3 là gì?


235

Cách chính xác để chuyển đổi byte thành chuỗi hex trong Python 3 là gì?

Tôi thấy các tuyên bố về một bytes.hexphương pháp, bytes.decodecodec và đã thử các chức năng có thể khác ít gây ngạc nhiên nhất mà không có kết quả. Tôi chỉ muốn byte của tôi là hex!


"Không có kết quả"? Những vấn đề cụ thể hoặc lỗi bạn đang nhận được? Vui lòng hiển thị mã và lỗi.
S.Lott

Câu trả lời:



95

Sử dụng binasciimô-đun:

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

Xem câu trả lời này: chuỗi Python 3.1.1 thành hex


8
Điều này là tốt Lưu ý rằng bạn có thể chuyển đổi hex thành byte bằng byte.fromhex (hex_str), nhưng bạn không thể chuyển đổi byte thành hex bằng byte.tohex () - lý do này là gì?
nagylzs

1
Tôi đoán mối quan hệ giữa byte và hex không phải là thuộc tính của một trong hai (điều này không trả lời tại sao fromhex lại ở đó). Có vẻ như đó không chỉ là một sự giám sát mà là một điều đã được tranh cãi: bug.python.org/su3532#msg70950 . Q: Sẽ có hại khi có phương thức tohex của đối tượng byte để thực hiện nhiệm vụ này chứ? A: IMO, vâng, nó sẽ. Nó làm phức tạp mã và rút ra sự tập trung từ cách tiếp cận phù hợp để chuyển đổi dữ liệu (cụ thể là các hàm - không phải các phương thức).
Mu Tâm

3
Điều này thực sự trả lời câu hỏi? Nó không trả về một hex strnhưng a bytes. Tôi biết rằng OP có vẻ hài lòng với câu trả lời nhưng sẽ tốt hơn nếu mở rộng câu trả lời này để bao gồm .decode("ascii")cả việc chuyển đổi nó thành "chuỗi"
RubenLaguna

3
Tôi đã nghĩ rằng nhiều người đáp ứng câu hỏi / câu trả lời này để tìm cách in ra bytes. Nếu bạn print(b'666f6f')nhận được btrong bản in. Nếu bạn .decode("ascii")thì bạn không. Chỉ cần suy nghĩ về cách những người thực sự có bytes(nhị phân thực sự với các mục> 128, không phải chuỗi ascii) muốn in ra nó.
RubenLaguna

5
@nagylzs: có .hex()phương pháp trong Python 3.5+
JFS

43

Python có các codec tiêu chuẩn byte-byte để thực hiện các phép biến đổi thuận tiện như trích dẫn có thể in được (phù hợp với 7 bit ascii), base64 (phù hợp với chữ số), thoát hex, nén gzip và bz2. Trong Python 2, bạn có thể làm:

b'foo'.encode('hex')

Trong Python 3, str.encode/ bytes.decodehoàn toàn dành cho các byte <-> str chuyển đổi. Thay vào đó, bạn có thể làm điều này, hoạt động trên Python 2 và Python 3 ( s / encode / decode / g cho nghịch đảo):

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

Bắt đầu với Python 3.4, có một tùy chọn ít khó xử hơn:

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

Các codec misc này cũng có thể truy cập được bên trong các mô-đun của riêng họ (base64, zlib, bz2, uu, quopri, binascii); API ít nhất quán hơn, nhưng đối với các codec nén, nó cung cấp nhiều quyền kiểm soát hơn.


1
sử dụng python 3.3:LookupError: unknown encoding: hex
Janus Troelsen

@JanusTroelsen: thử 'hex_codec' . Hoặc chỉ cần sử dụng binascii.hexlify(b'foo')trực tiếp
jfs

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

hoạt động trong Python 3.3 (vì vậy "hex_codec" thay vì "hex").


Có lẽ thú vị, trong Python 3,4 "hex" hoặc "hex_codec" hoạt động tốt.
Stephen Paulger

6

Phương thức binascii.hexlify()sẽ chuyển đổi bytesthành một byteschuỗi hex ascii. Điều đó có nghĩa là mỗi byte trong đầu vào sẽ được chuyển đổi thành hai ký tự ascii. Nếu bạn muốn một sự thật strthì bạn có thể .decode("ascii")kết quả.

Tôi bao gồm một đoạn trích minh họa nó.

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

từ chuỗi hex "0a160a04"để có thể quay trở lại bytesvới binascii.unhexlify("0a160a04")mang đến cho trở lạib'\n\x16\n\x04'


3

OK, câu trả lời sau đây hơi vượt quá phạm vi nếu bạn chỉ quan tâm đến Python 3, nhưng câu hỏi này là lần truy cập đầu tiên của Google ngay cả khi bạn không chỉ định phiên bản Python, vì vậy đây là cách hoạt động trên cả Python 2 Python 3 .

Tôi cũng đang giải thích câu hỏi về việc chuyển đổi byte thành strloại: đó là byte-y trên Python 2 và Unicode-y trên Python 3.

Cho rằng, cách tiếp cận tốt nhất mà tôi biết là:

import six

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

Khẳng định sau đây sẽ đúng với Python 2 hoặc Python 3, giả sử bạn chưa kích hoạt unicode_literalstương lai trong Python 2:

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

(Hoặc bạn có thể sử dụng ''.join()để bỏ khoảng trắng giữa các byte, v.v.)


3

nó có thể được sử dụng bộ định dạng định %x02dạng định dạng và xuất giá trị hex. Ví dụ:

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

Theo tôi, đó là câu trả lời tốt nhất vì nó hoạt động với mọi phiên bản Python và không cần nhập. Tuy nhiên, tôi sẽ hiển thị tốt hơn các chuỗi hexa bằng chữ in hoares.upper()
Bruno L.


0

Nếu bạn muốn chuyển đổi b '\ x61' thành 97 hoặc '0x61', bạn có thể thử điều này:

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

Tham khảo: https://docs.python.org/3.5/l Library /struct.html


Bằng cách nào đó giúp tôi với Esp32
Tejas Tank
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.