web-dev-qa-db-fra.com

Imprimer une chaîne sous forme d'octets hexadécimaux?

J'ai cette chaîne: Hello world !! et je veux l'imprimer en utilisant Python comme 48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21.

hex() ne fonctionne que pour les entiers. 

Comment ceci peut être fait?

137
Eduard Florinescu

Vous pouvez transformer votre chaîne en un générateur int, appliquer un formatage hexadécimal à chaque élément et s’intercaler avec un séparateur

>>> 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
205
Fedor Gogolev
':'.join(x.encode('hex') for x in 'Hello World!')
155
Aesthete

Pour Python 2.x:

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

Le code ci-dessus sera ne fonctionnera pas avec Python 3.x, pour 3.x, le code ci-dessous fonctionnera:

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

Une autre réponse en deux lignes que certains pourraient trouver plus facile à lire, et qui aide au débogage des sauts de ligne ou autres caractères impairs dans une chaîne:

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

Quelques compléments à la réponse de Fedor Gogolev:

Premièrement, si la chaîne contient des caractères dont le 'code ASCII' est inférieur à 10, ils ne seront pas affichés comme requis. Dans ce cas, le format correct devrait être {: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'
                                           ^^

Deuxièmement, si votre "chaîne" est en réalité une "chaîne d'octets" - et puisque la différence compte dans Python 3 -, vous préférerez peut-être ce qui suit:

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

Veuillez noter qu'il n'est pas nécessaire de convertir le code ci-dessus car un objet d'octets est défini as "une séquence d'entiers immuables comprise entre 0 et <256".

19
Sylvain Leroux

Imprimer une chaîne sous forme d'octets hexadécimaux?

La réponse acceptée donne:

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

résultats: 

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

La réponse acceptée ne fonctionne que tant que vous utilisez des octets (principalement des caractères ascii). Mais si vous utilisez unicode, par exemple:

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

Vous devez convertir en octets en quelque sorte.

Si votre terminal n'accepte pas ces caractères, vous pouvez décoder depuis utf-8 ou utiliser les noms (pour pouvoir coller et exécuter le code avec moi):

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}"
)

Alors on voit que: 

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

résultats

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

un résultat médiocre/inattendu - ce sont les points de code qui se combinent pour faire le graphemes nous voyons en unicode, du consortium unicode - représentant des langues du monde entier. C'est pas comment nous stockons ces informations afin qu'elles puissent être interprétées par d'autres sources.

Pour autoriser une autre source à utiliser ces données, nous aurions généralement besoin de convertir au codage utf-8, par exemple, pour enregistrer cette chaîne d'octets sur le disque ou pour la publier au format HTML. Nous avons donc besoin de cet encodage pour convertir les points de code en unités de code de utf-8 - en Python 3, ord n’est pas nécessaire car bytes sont des itérables d’entiers:

>>> ":".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'

Ou peut-être plus élégamment, en utilisant les nouvelles f-strings (uniquement disponibles dans 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, passez c à ord en premier, c.-à-d. ord(c) - d'autres exemples:

>>> ":".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'
8
Aaron Hall

Vous pouvez utiliser hexdump 's

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

(ajoutez .lower() si vous avez besoin de minuscules). Cela fonctionne à la fois pour Python 2 et 3.

7
Tobias Kienzler

L'utilisation des fonctions map et lambda peut générer une liste de valeurs hexadécimales pouvant être imprimées (ou utilisées à d'autres fins).

>>> 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']
6
BrendanSimon

Cela peut être fait de différentes manières:

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

La sortie de celui-ci sera en hexa comme suit:

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

2
Ghansham

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

Ceci est similaire à la réponse de @ Aesthete.

1
pylang

Juste pour la commodité, très 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'
1
BerndSchmitt

Utilisation de base64.b16encode dans python2 (son intégré)

>>> 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'
0
Shiplu Mokaddim