1

some device returns data (hex bytes) in the form of

data = b'\x07\x89\x00\x00\x12\x34'

How can I convert this to something in the form of the following?

['0x0789', '0x0000', '0x1234']

I already tried compositions of hexlify. I am using Python 3.5.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • I think your question title is a little misleading. What you actually want is to convert \xAB\xCD to \xABCD for a sequence of bytes and get the string representation. Can you come up with a better title? – timgeb Feb 05 '16 at 11:27

3 Answers3

0

Take groups of two from your bytes object. Multiply the first value from each group with 16**2. Add the two values. Use hex on the result to convert it to its string representation.

>>> [hex(data[i]*16**2 + data[i+1]) for i in range(0,len(data),2)]
['0x789', '0x0', '0x1234']

I assume that you don't need your strings padded with useless zeros for now.

timgeb
  • 76,762
  • 20
  • 123
  • 145
0

Use the struct module; it has unpack function which allows to specify the chunk size size (byte, 2-byte, 4-bytes) and endianess in the data. If what you have is big-endian half-word sized data chunks, then the right format key is ">H".

To parse all data at one, add count in the format specifier: for example ">3H" for you input array. You can also write the number of fields dynamically.

Full example:

import struct
data = b'\x07\x89\x00\x00\x12\x34'
d = struct.unpack(">{}H".format(len(data) // 2), data) # extract fields
result = [hex(x) for x in d] # convert to strings
kfx
  • 8,136
  • 3
  • 28
  • 52
  • @PatrickBateman My mistake, should have noticed this is Python 3. You should also tag the question with `python-3` tag. The difference is that `/` is always floating-point division in Py3, should use `//` instead. – kfx Feb 05 '16 at 13:07
0

There are two steps:

  1. Chunk the input bytestring into 2-byte sequences
  2. Display the sequences as hex literals.

You could use array module from stdlib:

import sys
from array import array

a = array('H', data)
if sys.byteorder != 'big':
    a.byteswap() # use big-endian order
result = ['0x%04X' % i for i in a]
# -> ['0x0789', '0x0000', '0x1234']

It is efficient, especially if you need to read data from a file.

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670