83

I need to create a string of hex digits from a list of random integers (0-255). Each hex digit should be represented by two characters: 5 - "05", 16 - "10", etc.

Example:

Input: [0,1,2,3,127,200,255], 
Output: 000102037fc8ff

I've managed to come up with:

#!/usr/bin/env python

def format_me(nums):
    result = ""
    for i in nums:
        if i <= 9:
            result += "0%x" % i
        else:
            result += "%x" % i
    return result

print format_me([0,1,2,3,127,200,255])

However, this looks a bit awkward. Is there a simpler way?

SiHa
  • 7,830
  • 13
  • 34
  • 43
facha
  • 11,862
  • 14
  • 59
  • 82

12 Answers12

179

Just for completeness, using the modern .format() syntax:

>>> numbers = [1, 15, 255]
>>> ''.join('{:02X}'.format(a) for a in numbers)
'010FFF'
gak
  • 32,061
  • 28
  • 119
  • 154
71
''.join('%02x'%i for i in input)
vartec
  • 131,205
  • 36
  • 218
  • 244
  • 4
    Besides the fact there's just a code snippet without any explanation (bad SO practice), I'm not sure why this answer is upvoted less than the one below it. Using the `%` syntax in Python 3 makes it backwards compatible. I highly recommend this solution over the other one. –  Apr 16 '19 at 04:46
  • @JoshuaDetwiler `%` vs `format` is discussed here: https://stackoverflow.com/questions/5082452/string-formatting-vs-format – Philip Couling Mar 16 '20 at 17:12
52

The most recent and in my opinion preferred approach is the f-string:

''.join(f'{i:02x}' for i in [1, 15, 255])

Format options

The old format style was the %-syntax:

['%02x'%i for i in [1, 15, 255]]

The more modern approach is the .format method:

 ['{:02x}'.format(i) for i in [1, 15, 255]]

More recently, from python 3.6 upwards we were treated to the f-string syntax:

[f'{i:02x}' for i in [1, 15, 255]]

Format syntax

Note that the f'{i:02x}' works as follows.

  • The first part before : is the input or variable to format.
  • The x indicates that the string should be hex. f'{100:02x}' is '64', f'{100:02d}' (decimal) is '100' and f'{100:02b}' (binary) is '1100100'.
  • The 02 indicates that the string should be left-filled with 0's to minimum length 2. f'{100:02x}' is '64' and f'{100:30x}' is ' 64'.

See pyformat for more formatting options.

Roelant
  • 4,508
  • 1
  • 32
  • 62
  • Yes, f-strings all the way! [Pyformat.info](https://pyformat.info/) has a comprehensive collection of formatting tricks. Although it's slightly outdated, as it still considers the `.format()` method recent, everything noted there can also be used with f-strings too. – pfabri May 08 '20 at 19:30
  • 1
    By far the best answer. Complete with all formatting options, each one using the simplest builtin way. – MestreLion Aug 24 '20 at 21:28
  • Easily the best answer. The bit on pyformat is key – rymanso May 10 '22 at 00:02
39

Python 2:

>>> str(bytearray([0,1,2,3,127,200,255])).encode('hex')
'000102037fc8ff'

Python 3:

>>> bytearray([0,1,2,3,127,200,255]).hex()
'000102037fc8ff'
David Avsajanishvili
  • 7,678
  • 2
  • 22
  • 24
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • This is likely the most performant option for Python 3 vs. the string formatting approaches (at least based on a few quick tests I ran myself; your mileage may vary). – kgriffs Jun 01 '20 at 20:01
  • A variant of this that will work on either Python 2 or 3 is: ```python import codecs ; str(codecs.encode(bytearray([0,1,2,3,127,200,255]), 'hex').decode()) ``` – Alissa H Jun 11 '21 at 03:24
18

Yet another option is binascii.hexlify:

a = [0,1,2,3,127,200,255]
print binascii.hexlify(bytes(bytearray(a)))

prints

000102037fc8ff

This is also the fastest version for large strings on my machine.

In Python 2.7 or above, you could improve this even more by using

binascii.hexlify(memoryview(bytearray(a)))

saving the copy created by the bytes call.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
13

Similar to my other answer, except repeating the format string:

>>> numbers = [1, 15, 255]
>>> fmt = '{:02X}' * len(numbers)
>>> fmt.format(*numbers)
'010FFF'
gak
  • 32,061
  • 28
  • 119
  • 154
  • Just as a complementary to this answer: if you want to print the hex in lower case, use "{:02x}.format(number)` – JiaHao Xu Apr 14 '19 at 11:31
6

Starting with Python 3.6, you can use f-strings:

>>> number = 1234
>>> f"{number:04x}"
'04d2'
roskakori
  • 3,139
  • 1
  • 30
  • 29
4
a = [0,1,2,3,127,200,255]
print str.join("", ("%02x" % i for i in a))

prints

000102037fc8ff

(Also note that your code will fail for integers in the range from 10 to 15.)

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
1

From Python documentation. Using the built in format() function you can specify hexadecimal base using an 'x' or 'X' Example:

x= 255 print('the number is {:x}'.format(x))

Output:

the number is ff

Here are the base options

Type
'b' Binary format. Outputs the number in base 2. 'c' Character. Converts the integer to the corresponding unicode character before printing. 'd' Decimal Integer. Outputs the number in base 10. 'o' Octal format. Outputs the number in base 8. 'x' Hex format. Outputs the number in base 16, using lower- case letters for the digits above 9. 'X' Hex format. Outputs the number in base 16, using upper- case letters for the digits above 9. 'n' Number. This is the same as 'd', except that it uses the current locale setting to insert the appropriate number separator characters. None The same as 'd'.

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • Welcome to SO! Have you seen that the question was posed almost 10 years ago and has an accepted answer? Whenever that's the case please answer only if you can offer a truly substantial improvement. (Besides, I think you misunderstood the question: It wasn't about how to format in hex, it was about a specific string creation.) – Timus Oct 04 '20 at 00:12
0

With python 2.X, you can do the following:

numbers = [0, 1, 2, 3, 127, 200, 255]
print "".join(chr(i).encode('hex') for i in numbers)

print

'000102037fc8ff'
selfboot
  • 1,490
  • 18
  • 23
0

Example with some beautifying, similar to the sep option available in python 3.8

def prettyhex(nums, sep=''):
    return sep.join(f'{a:02x}' for a in nums)

numbers = [0, 1, 2, 3, 127, 200, 255]
print(prettyhex(numbers,'-'))

output

00-01-02-03-7f-c8-ff
Marco
  • 580
  • 7
  • 10
0

Using python string format() this can be done.

Code:

n = [0,1,2,3,127,200,255]
s = "".join([format(i,"02X") for i in n])
print(s)

Output:

000102037FC8FF
RITA KUSHWAHA
  • 351
  • 3
  • 7