tags:

views:

189

answers:

5

How do I convert a string in Python to its ASCII hex representants?

Example: I want to result '\x00\x1b\xd4}\xa4\xf3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' in 001bd47da4f3.

+3  A: 
>>> text = '\x00\x1b\xd4}\xa4\xf3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'.rstrip('\0')
>>> print "".join("%02x" % ord(c) for c in text)
001bd47da4f3

As per martineau's comment, here is the Python 3 way:

>>> "".join(format(ord(c),"02x") for c in text)
Ryan Ginstrom
`%02x` would be better.
Manuel Faux
OK, I changed it to use %02x
Ryan Ginstrom
+1 because it's the best answer and it's not Python version dependent.
martineau
I chose this solution because I think it's the most intuitive; but @martineau: it IS Python version dependent. As far as I know is the `%` parameter not supported anymore in Python 3.
Manuel Faux
@Manuel Faux: Oops, my mistake. Well, since it *could* changed to: `print "".join(format(ord(c),"02x") for c in text)` which would at least make it work from 2.6 to 3.x, I won't take the +1 back since it was close. ;-)
martineau
@Manuel Faux, @Ryan Ginstrom: See my own Python version independent answer below which doesn't rely on string formatting or interpolation.
martineau
@Ryan Ginstrom: Actually the `"".join(format(ord(c),"02x") for c in text)` version should work in Python 2.6, 2.7, *and* Python 3.
martineau
A: 

binascii.hexlify():

import binascii

byte_string = '\x00\x1b\xd4}\xa4\xf3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' 
print binascii.hexlify(byte_string.rstrip('\x00'))

# -> 001bd47da4f3

See @John Machin's answer.

J.F. Sebastian
It will give a wrong result (I believe) for `\xf0\x00...` You should rstrip the input not the output.
KennyTM
Stripping the output is correct, I think. He wants to remove tailing zeros in the result.
Manuel Faux
that will remote too many zeroes, i.e. '\xf0' will result in 'f', not 'f0'
Ivo van der Wijk
Also, rstrip('00') does not work the way you seem to expect. It takes a class of characters to remove, not a specific sequence. In other words, it's equal to .rstrip("0")
Ivo van der Wijk
@KennyTM, @Ivo van der Wijk indeed, .rstrip() doesn't work in this case.
J.F. Sebastian
Ryan Ginstrom provided a better alternative. http://stackoverflow.com/questions/3850531/convert-python-string-to-its-ascii-representants/3850544#3850544
J.F. Sebastian
-1 Bizarre Baroque Byzantine Bassackwards Solution of the Month
John Machin
+3  A: 

With python 2.x you can encode a string to it's hex representation. It will not work with python3.x

>>> print '\x00\x1b\xd4}\xa4\xf3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'.encode("hex")
'001bd47da4f300000000000000000000'

It's not entirely clear if you have a literal string containing the escapes (so basically r'\x00\x1b' and so on) or not. Also, it's unclear why you don't expect the trailing zeroes, but you can remove those before the encode using .rstrip("\x00")

Ivo van der Wijk
Good point about the possible embedded escapes. Also strange that everyone is using the sample input, but no one has commented about the fact that it's messed-up (missing '7d' and has '}' in it) -- yet all give desired output...
martineau
} doesn't need an escape, but escaped it would have been \x7d. The string makes perfect sense, just not all characters are escaped.
Ivo van der Wijk
It's entirely clear from the OP's input and output that the input is '\x00\x1b' etc not r'\x00\x1b' etc.
John Machin
*Nothing* in this question is clear.
Glenn Maynard
@Ivo van der Wijk: Wow, can't believe I didn't notice that '}' is \x7d -- guess @Glenn Maynard is right.
martineau
+3  A: 

Alternative:

[Python 2.7]
>>> data = '\x00\x1b\xd4}\xa4\xf3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> import binascii
>>> binascii.b2a_hex(data.rstrip('\x00'))
'001bd47da4f3'
>>>

[Python 3.1.2]
>>> data = b'\x00\x1b\xd4}\xa4\xf3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> import binascii
>>> binascii.b2a_hex(data.rstrip(b'\x00'))
b'001bd47da4f3'
>>>
John Machin
`hexlify()` might be more readable.
J.F. Sebastian
@J.F. Sebastian: "hexlify" is silly, it's not even a portmanteau word (that would be "hexify") whereas a few seconds perusal of the binascii docs reveals that the non-silly names follow a pattern ... b2a_hex means "binary to ascii, hex mode"
John Machin
@John Machin: FWIW, whether or not `hexlify()` a "proper" portmanteau or just seems silly to you, it **is** one of the two names for same function in the `binascii` module -- so consider that obviously others must have also thought it's a more descriptive or readable name, too.
martineau
+2  A: 

Here's another answer that ought to work with all Python versions from 3.x all the way back to 2.0 (min version according to pyqver). Despite that, because it's based on a simple table (not dict) lookup, it should also be relatively quick.

A little one-time set-up is required, but is very simple and avoids using the any of the many enhancements that have were added (or removed) along the way in a quest for version independence.

numerals = "0123456789abcdef"
hexadecimal = [i+j for i in numerals for j in numerals]

text = '\x00\x1b\xd4}\xa4\xf3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'    
print ''.join([hexadecimal[ord(c)] for c in text.rstrip('\0')])
# 001bd47da4f3
martineau