I have this string: Hello, World!
and I want to print it using Python as '48:65:6c:6c:6f:2c:20:57:6f:72:6c:64:21'.
hex()
works only for integers.
How can it be done?
I have this string: Hello, World!
and I want to print it using Python as '48:65:6c:6c:6f:2c:20:57:6f:72:6c:64:21'.
hex()
works only for integers.
How can it be done?
You can transform your string to an integer generator. Apply hexadecimal formatting for each element and intercalate with a separator:
>>> s = "Hello, World!"
>>> ":".join("{:02x}".format(ord(c)) for c in s)
'48:65:6c:6c:6f:2c:20:57:6f:72:6c:64:21
str
as hex doesn't really make sense; you'll want to print bytes
object as hex (convert str
to bytes
by calling .encode()
). –
Tease ":".join("{:02x}".format(ord(c)) for c in 'løl')
returns '6c:f8:6c'
, while ":".join("{:02x}".format(c) for c in 'løl'.encode())
produces the correct utf-8 representation '6c:c3:b8:6c'
. –
Tease ":".join("{:04x}".format(ord(c)) for c in s)
(replacing 02x
with 04x
to zero-pad each number to be 4 digits) instead –
Ammonic WARNING: Calling str(pkt) on Python 3 makes no sense!
–
Hellbox python2
strings are sequences of bytes; ord
gives a value between 0 and 0xff
. In python3
strings are sequences of unicode codepoints. ord
gives the number of the codepoint, which can be up to 0x10ffff
. In python3
you want to use the bytes
type, which you can get by encoding a string with .encode()
. –
Tease ':'.join(x.encode('hex') for x in 'Hello, World!')
h = binascii.hexlify(b"Hello world !!") to get hex string. b":".join(h[i:i+2] for i in range(0, len(h), 2))
to insert ':'
after every two hex digits in it. –
Manslaughter LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs
–
Ammonic For Python 2.x:
':'.join(x.encode('hex') for x in 'Hello, World!')
The code above will not work with Python 3.x. For 3.x, the code below will work:
':'.join(hex(ord(x))[2:] for x in 'Hello, World!')
':'.join("{:0>2}".format(hex(ord(x))[2:]) for x in 'Hello,\nWorld!').upper()
–
Glynas Another answer in two lines that some might find easier to read, and helps with debugging line breaks or other odd characters in a string:
For Python 2.7
for character in string:
print character, character.encode('hex')
For Python 3.7 (not tested on all releases of 3)
for character in string:
print(character, character.encode('utf-8').hex())
codecs.encode(<bytestring>, "hex")
does work, though. –
Mcgann import sys
; s="Déjà vu Besançon,Lupiñén,Šiauliai,Großräschen,Łódź,Аша,广东省,LA"
; for c in s:
; w=sys.stdout.write(c+":"+c.encode('utf-8').hex()+"||")
; (out) D:44||é:c3a9||j:6a||à:c3a0|| :20||v:76||u:75|| :20||B:42||e:65||s:73||a:61||n:6e||ç:c3a7||o:6f||n:6e||,:2c||L:4c||u:75||p:70||i:69||ñ:c3b1||é:c3a9||n:6e||,:2c||Š:c5a0||i:69||a:61||u:75||l:6c||i:69||a:61||i:69||,:2c||G:47||r:72||o:6f||ß:c39f||r:72||ä:c3a4||s:73||c:63||h:68||e:65||n:6e||,:2c||Ł:c581||ó:c3b3||d:64||ź:c5ba||,:2c||А:d090||ш:d188||а:d0b0||,:2c||广:e5b9bf||东:e4b89c||省:e79c81||,:2c||L:4c||A:41||
–
Airline Some complements to Fedor Gogolev's answer:
First, if the string contains characters whose ASCII code is below 10, they will not be displayed as required. In that case, the correct format should be {: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: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:21:21'
^^
Second, if your "string" is in reality a "byte string" -- and since the difference matters in Python 3 -- you might prefer the following:
>>> 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:21:21'
Please note there is no need for conversion in the above code as a bytes object is defined as "an immutable sequence of integers in the range 0 <= x < 256".
Print a string as hex bytes?
The accepted answer gives:
s = "Hello world !!"
":".join("{:02x}".format(ord(c)) for c in s)
returns:
'48:65:6c:6c:6f:20:77:6f:72:6c:64:20:21:21'
The accepted answer works only so long as you use bytes (mostly ascii characters). But if you use unicode, e.g.:
a_string = u"Привет мир!!" # "Prevyet mir", or "Hello World" in Russian.
You need to convert to bytes somehow.
If your terminal doesn't accept these characters, you can decode from UTF-8 or use the names (so you can paste and run the code along with me):
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}"
)
So we see that:
":".join("{:02x}".format(ord(c)) for c in a_string)
returns
'41f:440:438:432:435:442:20:43c:438:440:21:21'
a poor/unexpected result - these are the code points that combine to make the graphemes we see in Unicode, from the Unicode Consortium - representing languages all over the world. This is not how we actually store this information so it can be interpreted by other sources, though.
To allow another source to use this data, we would usually need to convert to UTF-8 encoding, for example, to save this string in bytes to disk or to publish to html. So we need that encoding to convert the code points to the code units of UTF-8 - in Python 3, ord
is not needed because bytes
are iterables of integers:
>>> ":".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'
Or perhaps more elegantly, using the new f-strings (only available in 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'
In Python 2, pass c
to ord
first, i.e. ord(c)
- more examples:
>>> ":".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'
You can use hexdump
's:
import hexdump
hexdump.dump("Hello, World!", sep=":")
(append .lower()
if you require lower-case). This works for both Python 2 and 3.
pip install -U hexdump --proxy http://proxy.address:port
–
Lookeron sudo
with pip
, which messed up pacman
... –
Marquittamarr Using map and lambda function can produce a list of hex values, which can be printed (or used for other purposes)
>>> 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']
[hex(ord(c)) for c in s]
–
Ammonic A bit more general for those who don't care about Python 3 or colons:
from codecs import encode
data = open('/dev/urandom', 'rb').read(20)
print(encode(data, 'hex')) # Data
print(encode(b"hello", 'hex')) # String
With f-string:
"".join(f"{ord(c):x}" for c in "Hello")
Use any delimiter:
>>> "⚡".join(f"{ord(c):x}" for c in "Hello")
'48⚡65⚡6c⚡6c⚡6f'
":".join(f"{ord(c):x}" for c in "Hello")
, you may change it into any delimiter –
Literal This can be done in the following ways:
from __future__ import print_function
str = "Hello, World!"
for char in str:
mm = int(char.encode('hex'), 16)
print(hex(mm), sep=':', end=' ')
The output of this will be in hexadecimal as follows:
0x48 0x65 0x6c 0x6c 0x6f 0x20 0x57 0x6f 0x72 0x6c 0x64 0x21
__future__
is a standard library available in recent versions of Python 2 that can be used to make features normally only in Python 3 backwards-compatible. In this answer, it's used to get the print(text)
"print function" feature, which replaces the print text
syntax from Python 2. See the Python docs. –
Conciliar LookupError: 'hex' is not a text encoding; use codecs.encode() to handle arbitrary codecs
–
Adlee For something that offers more performance than ''.format()
, you can use this:
>>> ':'.join( '%02x'%(v if type(v) is int else ord(v)) for v in 'Hello, World!' )
'48:65:6C:6C:6F:2C:20:57:6F:72:6C:64:21'
>>>
>>> ':'.join( '%02x'%(v if type(v) is int else ord(v)) for v in b'Hello, World!' )
'48:65:6C:6C:6F:2C:20:57:6F:72:6C:64:21'
>>>
I am sorry this couldn't look nicer.
It would be nice if one could simply do '%02x'%v
, but that only takes int...
But you'll be stuck with byte-strings b''
without the logic to select ord(v)
.
Just for convenience, very simple.
def hexlify_byteString(byteString, delim="%"):
''' Very simple way to hexlify a byte string 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:2C:20:57:6F:72:6C:64:21'
© 2022 - 2024 — McMap. All rights reserved.
str
or Python 3bytestring
), as there is no unequivocal transformation of a character into an integer in 0…255. Thus, character strings (Python 2unicode
and Python 3str
) first require some encoding before being convertible in this hexadecimal format. Aaron Hall's answer exemplifies this. – Mcgann