¿Cuál es la forma correcta de convertir bytes a una cadena hexadecimal en Python 3?


236

¿Cuál es la forma correcta de convertir bytes a una cadena hexadecimal en Python 3?

Veo reclamos de un bytes.hexmétodo, bytes.decodecódecs, y he probado otras posibles funciones de menor asombro sin resultado. ¡Solo quiero mis bytes como hexadecimales!


"en vano"? ¿Qué problemas o errores específicos tienes? Por favor, muestre el código y los errores.
S.Lott

Respuestas:



95

Usa el binasciimódulo:

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

Ver esta respuesta: Python 3.1.1 cadena a hexadecimal


8
Esto es bueno. Alucinante es que puedes convertir hexadecimal a bytes usando bytes.fromhex (hex_str), pero no puedes convertir bytes a hexadecimal usando bytes.tohex (): ¿cuál es la razón en esto?
nagylzs

1
Supongo que la relación entre bytes y hexadecimal no es una propiedad de ninguno de los dos (lo que no responde por qué fromhex está allí). Parece que no fue solo un descuido, sino algo sobre lo que se discutió: bugs.python.org/issue3532#msg70950 . P: ¿Le dolería tener el método tohex del objeto bytes para realizar esta tarea también? A: OMI, sí, lo haría. Complica el código y aleja el enfoque del enfoque adecuado para la conversión de datos (es decir, funciones, no métodos).
Mu Mind

3
¿Esto realmente responde la pregunta? No devuelve un hex strpero a bytes. Yo sé que el PO parece contento con la respuesta, pero no va a ser mejor para expandir esta respuesta para incluir .decode("ascii")también a convertirla en una "cadena"
RubenLaguna

3
Estaba pensando que muchas personas llegan a esta pregunta / respuesta buscando una forma de imprimir a bytes. Si print(b'666f6f')obtienes el ben la impresión. Si tú .decode("ascii")entonces no lo haces. Solo pensando en cómo aquellos que realmente tenían un bytes(binario verdadero con elementos> 128, no una cadena ascii) querían imprimirlo.
RubenLaguna

55
@nagylzs: hay un .hex()método en Python
3.5+

43

Python tiene códecs estándar de bytes a bytes que realizan transformaciones convenientes como imprimible entre comillas (encaja en 7 bits ascii), base64 (encaja en alfanuméricos), escape hexadecimal, compresión gzip y bz2. En Python 2, podrías hacer:

b'foo'.encode('hex')

En Python 3, str.encode/ bytes.decodeson estrictamente para conversiones bytes <-> str. En cambio, puede hacer esto, que funciona en Python 2 y Python 3 ( s / encode / decode / g para el inverso):

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

Comenzando con Python 3.4, hay una opción menos incómoda:

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

Estos códecs misceláneos también son accesibles dentro de sus propios módulos (base64, zlib, bz2, uu, quopri, binascii); la API es menos consistente, pero para los códecs de compresión ofrece más control.


1
usando Python 3.3:LookupError: unknown encoding: hex
Janus Troelsen

@JanusTroelsen: prueba 'hex_codec' . O simplemente usar binascii.hexlify(b'foo')directamente
jfs

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

funciona en Python 3.3 (por lo tanto, "hex_codec" en lugar de "hex").


Quizás sea interesante, en Python 3.4 "hex" o "hex_codec" funciona bien.
Stephen Paulger

6

El método binascii.hexlify()se convertirá bytesen una bytesrepresentación de la cadena hexadecimal ascii. Eso significa que cada byte en la entrada se convertirá en dos caracteres ascii. Si quieres una verdadera strsalida, entonces puedes obtener .decode("ascii")el resultado.

Incluí un fragmento que lo ilustra.

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

desde la cadena hexadecimal "0a160a04"a puede volver a la bytescon la binascii.unhexlify("0a160a04")que devuelveb'\n\x16\n\x04'


3

De acuerdo, la siguiente respuesta está un poco fuera de alcance si solo te importa Python 3, pero esta pregunta es el primer éxito de Google incluso si no especificas la versión de Python, así que aquí hay una manera que funciona tanto en Python 2 como en Python 3 .

También estoy interpretando que la pregunta es sobre la conversión de bytes al strtipo: es decir, bytes-y en Python 2 y Unicode-y en Python 3.

Dado eso, el mejor enfoque que conozco es:

import six

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

La siguiente afirmación será cierta para Python 2 o Python 3, suponiendo que no haya activado el unicode_literalsfuturo en Python 2:

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

(O puede usar ''.join()para omitir el espacio entre los bytes, etc.)


3

se puede usar el especificador de %x02formato que formatea y genera un valor hexadecimal. Por ejemplo:

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

Según yo, es la mejor respuesta porque funciona con todas las versiones de Python y no necesita ninguna importación. Sin embargo, sería mejor mostrar cadenas hexa en mayúsculasres.upper()
Bruno L.


0

Si desea convertir b '\ x61' a 97 o '0x61', puede intentar esto:

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

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


De alguna manera me ayuda con esp32
Tejas Tank
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.