Jo gi
Jo gi

Reputation: 23

How can I convert a bytestring array in a hex string in Python 3.4?

I have a bytestring from a socket connection:

>>> var
b'\xb5\x1a'

How can i convert this (little endian order) into a Hex string like:

>>> var2
0x1AB5

I tried:

>>> var.decode('utf-8')
Traceback (most recent call last):File "<stdin>", line 1, in <module> UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb5 in position 0: invalid start byte

>>> var.from_bytes(2,'little')
Traceback (most recent call last):File "<stdin>", line 1, in <module> AttributeError: 'bytes' object has no attribute 'from_bytes'

Upvotes: 2

Views: 1731

Answers (1)

vaultah
vaultah

Reputation: 46593

The int.from_bytes method will help.

int.from_bytes(bytes, byteorder, *, signed=False) -> int

Return the integer represented by the given array of bytes.

...

If byteorder is 'little', the most significant byte is at the end of the byte array.

It will convert bytes to integer:

In [1]: int.from_bytes(b'\xb5\x1a', 'little') # 'little' for little-endian order
Out[1]: 6837

Then you can use hex

In [2]: hex(int.from_bytes(b'\xb5\x1a', 'little'))
Out[2]: '0x1ab5'

or format(..., '#x')

In [3]: format(int.from_bytes(b'\xb5\x1a', 'little'), '#x')
Out[3]: '0x1ab5'

to get hexadecimal representation.

Other solutions include base64.b16encode

In [4]: import base64

In [5]: '0x' + base64.b16encode(b'\xb5\x1a'[::-1]).decode('ascii')
Out[5]: '0x1AB5'

and binascii.hexlify:

In [24]: '0x' + binascii.hexlify(b'\xb5\x1a'[::-1]).decode('ascii')
Out[24]: '0x1ab5'

Some timings for bytestr = b'\xb5\x1a':

In [32]: %timeit hex(int.from_bytes(bytestr, 'little'))
1000000 loops, best of 3: 267 ns per loop

In [33]: %timeit format(int.from_bytes(bytestr, 'little'), '#x')
1000000 loops, best of 3: 465 ns per loop

In [34]: %timeit '0x' + base64.b16encode(bytestr[::-1]).decode('ascii')
1000000 loops, best of 3: 746 ns per loop

In [35]: %timeit '0x' + binascii.hexlify(bytestr[::-1]).decode('ascii')
1000000 loops, best of 3: 545 ns per loop

For bytestr = b'\xb5\x1a' * 100:

In [37]: %timeit hex(int.from_bytes(bytestr, 'little'))
1000000 loops, best of 3: 992 ns per loop

In [38]: %timeit format(int.from_bytes(bytestr, 'little'), '#x')
1000000 loops, best of 3: 1.2 µs per loop

In [39]: %timeit '0x' + base64.b16encode(bytestr[::-1]).decode('ascii')
1000000 loops, best of 3: 1.38 µs per loop


In [40]: %timeit '0x' + binascii.hexlify(bytestr[::-1]).decode('ascii')
1000000 loops, best of 3: 983 ns per loop

int.from_bytes is (predictably) fast for small byte strings, binascii.hexlify is fast for longer byte strings.

Upvotes: 2

Related Questions