¿Imprimir una cadena como bytes hexadecimales?

Tengo esta cadena: Hello world !! y quiero imprimirlo usando Python como 48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21 .

hex() funciona solo para enteros.

¿Cómo puede hacerse esto?

Puede transformar su cadena en un generador int, aplicar formato hexadecimal para cada elemento e intercalar con separador:

 >>> s = "Hello world !!" >>> ":".join("{:02x}".format(ord(c)) for c in s) '48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21 
 ':'.join(x.encode('hex') for x in 'Hello World!') 

Para Python 2.x:

 ':'.join(x.encode('hex') for x in 'Hello World!') 

El código anterior no funcionará con Python 3.x , para 3.x, el código siguiente funcionará:

 ':'.join(hex(ord(x))[2:] for x in 'Hello World!') 

Otra respuesta en dos líneas que algunos pueden encontrar más fácil de leer, y ayuda a depurar saltos de línea u otros caracteres impares en una cadena:

 for character in string: print character, character.encode('hex') 

Algunos complementos a la respuesta de Fedor Gogolev:

Primero, si la cadena contiene caracteres cuyo ‘código ASCII’ está por debajo de 10, no se mostrarán según sea necesario. En ese caso, el formato correcto debe ser {:02x} :

 >>> s = "Hello unicode \u0005 !!" >>> ":".join("{0:x}".format(ord(c)) for c in s) '48:65:6c:6c:6f:20:75:6e:69:63:6f:64:65:20:5:20:21:21' ^ >>> ":".join("{:02x}".format(ord(c)) for c in s) '48:65:6c:6c:6f:20:75:6e:69:63:6f:64:65:20:05:20:21:21' ^^ 

Segundo, si su “cadena” es en realidad una “cadena de bytes” y, como la diferencia es importante en Python 3, es posible que prefiera lo siguiente:

 >>> s = b"Hello bytes \x05 !!" >>> ":".join("{:02x}".format(c) for c in s) '48:65:6c:6c:6f:20:62:79:74:65:73:20:05:20:21:21' 

Tenga en cuenta que no hay necesidad de conversión en el código anterior ya que los objetos de bytes se definen como “una secuencia inmutable de números enteros en el rango 0 <= x <256" .

¿Imprimir una cadena como bytes hexadecimales?

La respuesta aceptada da:

 s = "Hello world !!" ":".join("{:02x}".format(ord(c)) for c in s) 

devoluciones:

 '48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21' 

La respuesta aceptada funciona solo mientras se utilicen bytes (en su mayoría, caracteres ASCII). Pero si usas Unicode, por ejemplo:

 a_string = u"Привет мир!!" # "Prevyet mir, or "Hello World" in Russian. 

Necesitas convertir a bytes de alguna manera.

Si su terminal no acepta estos caracteres, puede decodificar desde utf-8 o usar los nombres (para que pueda pegar y ejecutar el código junto conmigo):

 a_string = ( "\N{CYRILLIC CAPITAL LETTER PE}" "\N{CYRILLIC SMALL LETTER ER}" "\N{CYRILLIC SMALL LETTER I}" "\N{CYRILLIC SMALL LETTER VE}" "\N{CYRILLIC SMALL LETTER IE}" "\N{CYRILLIC SMALL LETTER TE}" "\N{SPACE}" "\N{CYRILLIC SMALL LETTER EM}" "\N{CYRILLIC SMALL LETTER I}" "\N{CYRILLIC SMALL LETTER ER}" "\N{EXCLAMATION MARK}" "\N{EXCLAMATION MARK}" ) 

Así que vemos que:

 ":".join("{:02x}".format(ord(c)) for c in a_string) 

devoluciones

 '41f:440:438:432:435:442:20:43c:438:440:21:21' 

Un resultado pobre / inesperado: estos son los puntos de código que se combinan para hacer los grafemas que vemos en Unicode, del consorcio Unicode, que representan idiomas de todo el mundo. Sin embargo, no es así como almacenamos esta información, por lo que otras fonts pueden interpretarla.

Para permitir que otra fuente utilice estos datos, generalmente deberíamos convertir a la encoding utf-8, por ejemplo, para guardar esta cadena en bytes en el disco o para publicar en html. Así que necesitamos esa encoding para convertir los puntos de código en las unidades de código de utf-8 – en Python 3, ord no es necesario porque los bytes son iterables de los enteros:

 >>> ":".join("{:02x}".format(c) for c in a_string.encode('utf-8')) 'd0:9f:d1:80:d0:b8:d0:b2:d0:b5:d1:82:20:d0:bc:d0:b8:d1:80:21:21' 

O quizás más elegantemente, usando las nuevas f-strings (solo disponibles en Python 3):

 >>> ":".join(f'{c:02x}' for c in a_string.encode('utf-8')) 'd0:9f:d1:80:d0:b8:d0:b2:d0:b5:d1:82:20:d0:bc:d0:b8:d1:80:21:21' 

En Python 2, pase c a ord primero, es decir ord(c) – más ejemplos:

 >>> ":".join("{:02x}".format(ord(c)) for c in a_string.encode('utf-8')) 'd0:9f:d1:80:d0:b8:d0:b2:d0:b5:d1:82:20:d0:bc:d0:b8:d1:80:21:21' >>> ":".join(format(ord(c), '02x') for c in a_string.encode('utf-8')) 'd0:9f:d1:80:d0:b8:d0:b2:d0:b5:d1:82:20:d0:bc:d0:b8:d1:80:21:21' 

Puedes usar hexdump ‘s

 import hexdump hexdump.dump("Hello World", sep=":") 

(agregue .lower() si necesita minúsculas). Esto funciona tanto para Python 2 como para 3.

El uso de la función mapa y lambda puede producir una lista de valores hexadecimales, que se pueden imprimir (o utilizar para otros fines)

 >>> s = 'Hello 1 2 3 \x01\x02\x03 :)' >>> map(lambda c: hex(ord(c)), s) ['0x48', '0x65', '0x6c', '0x6c', '0x6f', '0x20', '0x31', '0x20', '0x32', '0x20', '0x33', '0x20', '0x1', '0x2', '0x3', '0x20', '0x3a', '0x29'] 

Esto se puede hacer de las siguientes maneras:

 from __future__ import print_function str = "Hello World !!" for char in str: mm = int(char.encode('hex'), 16) print(hex(mm), sep=':', end=' ' ) 

La salida de esto será en hexadecimal como sigue:

0x48 0x65 0x6c 0x6c 0x6f 0x20 0x57 0x6f 0x72 0x6c 0x64 0x20 0x21 0x21

Sólo por conveniencia, muy simple.

 def hexlify_byteString(byteString, delim="%"): ''' very simple way to hexlify a bytestring using delimiters ''' retval = "" for intval in byteString: retval += ( '0123456789ABCDEF'[int(intval / 16)]) retval += ( '0123456789ABCDEF'[int(intval % 16)]) retval += delim return( retval[:-1]) hexlify_byteString(b'Hello World!', ":") # Out[439]: '48:65:6C:6C:6F:20:57:6F:72:6C:64:21' 

En Python 3:

 ":".join(c.encode().hex() for c in "Hello world !!") # 48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21 

Esto es similar a la respuesta de @Aesthete.

Usando base64.b16encode en python2 (su incorporado)

 >>> s = 'Hello world !!' >>> h = base64.b16encode(s) >>> ':'.join([h[i:i+2] for i in xrange(0, len(h), 2)] '48:65:6C:6C:6F:20:77:6F:72:6C:64:20:21:21'