Печатать строку как шестнадцатеричные байты?

У меня есть эта строка: Hello world !!, и я хочу ее распечатать с помощью Python как 48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21.

hex() работает только для целых чисел.

Как это можно сделать?

Ответ 1

Вы можете преобразовать свою строку в генератор int, применить шестнадцатеричное форматирование для каждого элемента и интеркалировать с разделителем:

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

Ответ 2

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

Ответ 3

Для Python 2.x:

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

Приведенный выше код не работает с Python 3.x, для 3.x код ниже будет работать:

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

Ответ 4

Еще один ответ в двух строках, который некоторые могут найти более легким для чтения, а также помогает отлаживать разрывы строк или другие нечетные символы в строке:

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

Ответ 5

Некоторые дополнения к решению Федора Гоголева:

Во-первых, если строка содержит символы, "ASCII-код" которых меньше 10, они не будут отображаться по мере необходимости. В этом случае правильный формат должен быть {: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'
                                           ^^

Во-вторых, если ваша "строка" на самом деле является "байтовой строкой" - и поскольку разница имеет значение в Python 3, вы можете предпочесть следующее:

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

Обратите внимание, что в приведенном выше коде нет необходимости в преобразовании байтовых объектов как "неизменяемая последовательность целых чисел в диапазоне 0 <= x < 256".

Ответ 6

Вывести строку в виде шестнадцатеричных байтов?

Принятый ответ дает:

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'

Принятый ответ работает только до тех пор, пока вы используете байты (в основном символы ascii). Но если вы используете Unicode, например:

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

Вам нужно как-то преобразовать в байты.

Если ваш терминал не принимает эти символы, вы можете декодировать из utf-8 или использовать имена (чтобы вы могли вставить и запустить код вместе со мной):

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

Итак, мы видим, что:

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

возвращается

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

плохой/неожиданный результат - это кодовые точки, которые объединяются для создания графем, которые мы видим в юникоде, из консорциума юникод - представляющих языки во всем мире. Это не то, как мы на самом деле храним эту информацию, поэтому она может быть интерпретирована другими источниками.

Чтобы позволить другому источнику использовать эти данные, нам обычно необходимо преобразовать кодировку в utf-8, например, чтобы сохранить эту строку в байтах на диск или опубликовать в html. Поэтому нам нужна эта кодировка для преобразования кодовых точек в кодовые единицы utf-8 - в Python 3, ord не требуется, потому что bytes являются итерациями целых чисел:

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

Или, возможно, более элегантно, используя новые f-строки (доступно только в 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'

В Python 2 передайте c сначала ord, то есть ord(c) - больше примеров:

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

Ответ 7

Вы можете использовать hexdump

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

(добавьте .lower(), если вам нужен нижний регистр). Это работает как для Python 2, так и для 3.

Ответ 8

Использование карты и лямбда-функции может создавать список шестнадцатеричных значений, которые могут быть напечатаны (или использованы для других целей)

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

Ответ 9

Это можно сделать следующим образом:

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

Результат этого будет в шестнадцатеричном виде:

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

Ответ 10

Использование base64.b16encode в python2 (его встроенный)

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

Ответ 11

Просто для удобства, очень просто.

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'