Reputation: 46821
Is this the best way to convert a Python number to a hex string?
number = 123456789
hex(number)[2:-1].decode('hex')
Sometimes it doesn't work and complains about Odd-length string when you do 1234567890.
Clarification:
I am going from int to hex.
Also, I need it to be escaped.
IE: 1234567890 -> '\x49\x96\x02\xd2' not '499602D2'
Also, it needs to be able to take any Python integer. IE. something larger than an Int.
Edit:
Here is the best solution so far I have cobbled together from Paolo and Devin's post.
def hexify(num):
num = "%x" % num
if len(num) % 2:
num = '0'+num
return num.decode('hex')
Upvotes: 4
Views: 6806
Reputation: 457
'{0:b}'.format( number )
refer to http://docs.python.org/library/string.html
Upvotes: 1
Reputation: 589
one of the surest way, for arbitary numbers, is to use the 'array' module like this:
from array import array
binArr = array('B')
while(data):
d = data & 0xFF
binArr.append(d)
data >>= 8
hexStr = binArr.tostring()
Upvotes: 0
Reputation: 61589
As Paolo mentioned, string formatting is the way to go. Note that you can choose between lower and upper case letters:
>>> hex = lambda n: '%X' % n
>>> hex(42)
'2A'
>>> hex = lambda n: '%x' % n
>>> hex(42)
'2a'
>>> def escaped(n):
... s = hex(n)
... if len(s) & 1:
... s = '0' + s
... return ''.join(chr(int(s[i:i + 2], 16)) for i in range(0, len(s), 2))
...
>>> escaped(123)
'{'
>>> escaped(1234)
'\x04\xd2'
>>> escaped(12348767655764764654764445473245874398787989879879873)
'!\x01^\xa4\xdf\xdd(l\x9c\x00\\\xfa*\xf3\xb4\xc4\x94\x98\xa9\x03x\xc1'
Note that escaped adds a leading zero in case of an odd number of hex digits. This solution works for strings of any length.
Upvotes: 0
Reputation: 42203
I'm not sure exactly what you want, but have you looked at the struct
module?
Given
>>> hex(123456789)
'0x75bcd15'
You can do:
>>> struct.pack('i', 123456789)
'\x15\xcd[\x07'
Note that '\x5b' == '['
.
Also, you can reverse the endianness:
>>> struct.pack('>i', 123456789)
'\x07[\xcd\x15'
Edit: I'm not sure what you mean by "bigger than a long", since AFAIK longs in python are unbounded (except by memory). However, you can deal with bigger integers by just dividing and concatenating. e.g. given:
>>> n = 123456789012345678901234567890
the target is:
>>> hex(n)
'0x18ee90ff6c373e0ee4e3f0ad2L'
So:
>>> s = ''
>>> while n >= 2**32:
... n, r = divmod(n, 2**32)
... s = struct.pack('>l', r) + s
...
>>> s = struct.pack('>l', n) + s
See that s
matches the result of hex(n)
above:
>>> s
'\x00\x00\x00\x01\x8e\xe9\x0f\xf6\xc3s\xe0\xeeN?\n\xd2'
Upvotes: 5
Reputation: 56624
If you know how long your output strings should be, string formatting will work. For example, to get four-character strings, you need a formatted length of eight:
>>> "{0:08x}".format(123456789).decode("hex")
'\x07[\xcd\x15'
>>> "{0:08x}".format(1234567890).decode("hex")
'I\x96\x02\xd2'
This will prepend zeroes if your number doesn't "fill up" the string. For example, with six-character strings:
>>> "{0:012x}".format(123456789).decode("hex")
'\x00\x00\x07[\xcd\x15'
>>> "{0:012x}".format(1234567890).decode("hex")
'\x00\x00I\x96\x02\xd2'
Edit:
To "detect" the length of target strings, you can use the math.log
function:
>>> def int2str(n):
l = int(math.ceil(math.log(n, 256) / 2) * 4)
return ("{0:0{1}x}").format(n, l).decode("hex")
>>> int2str(123456789)
'\x07[\xcd\x15'
>>> int2str(1234567890)
'I\x96\x02\xd2'
Upvotes: 0
Reputation: 95606
Sometimes it doesn't work and complains about Odd-length string when you do 1234567890.
Because it doesn't make sense. How do you fit 'AAB' in a space that takes either 2 or 4 digits? Each byte is two hex characters. When you have an odd number of hex characters, the desired result is ambiguous. Do you want it to be the equivalent of 0AAB or AAB0? If you know which one you want it to be equivalent to, just add that character to the right place before decoding.
i.e. (('0' + foo) if len(foo) % 2 else foo).decode('hex')
where foo is a string of the form returned by %x.
Upvotes: 1
Reputation: 488694
You can use string formatting:
>>> number = 123456789
>>> hex = "%X" % number
>>> hex
'75BCD15'
Upvotes: 6