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.