How to convert a string of bytes into an int?

ghz 3months ago ⋅ 35 views

How can I convert a string of bytes into an int in python?

Say like this: 'y\xcc\xa6\xbb'

I came up with a clever/stupid way of doing it:

sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))

I know there has to be something builtin or in the standard library that does this more simply...

This is different from converting a string of hex digits for which you can use int(xxx, 16), but instead I want to convert a string of actual byte values.

UPDATE:

I kind of like James' answer a little better because it doesn't require importing another module, but Greg's method is faster:

>>> from timeit import Timer
>>> Timer('struct.unpack("<L", "y\xcc\xa6\xbb")[0]', 'import struct').timeit()
0.36242198944091797
>>> Timer("int('y\xcc\xa6\xbb'.encode('hex'), 16)").timeit()
1.1432669162750244

My hacky method:

>>> Timer("sum(ord(c) << (i * 8) for i, c in enumerate('y\xcc\xa6\xbb'[::-1]))").timeit()
2.8819329738616943

FURTHER UPDATE:

Someone asked in comments what's the problem with importing another module. Well, importing a module isn't necessarily cheap, take a look:

>>> Timer("""import struct\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""").timeit()
0.98822188377380371

Including the cost of importing the module negates almost all of the advantage that this method has. I believe that this will only include the expense of importing it once for the entire benchmark run; look what happens when I force it to reload every time:

>>> Timer("""reload(struct)\nstruct.unpack(">L", "y\xcc\xa6\xbb")[0]""", 'import struct').timeit()
68.474128007888794

Needless to say, if you're doing a lot of executions of this method per one import than this becomes proportionally less of an issue. It's also probably i/o cost rather than cpu so it may depend on the capacity and load characteristics of the particular machine.

Answers

To convert a string of bytes into an integer in Python, there are indeed simpler and more efficient ways to do it than your approach. The struct module provides a very convenient and fast way to handle this type of conversion.

Here’s how you can convert the byte string 'y\xcc\xa6\xbb' into an integer using struct.unpack:

import struct

# Convert bytes string into an integer using struct.unpack
byte_string = b'y\xcc\xa6\xbb'
result = struct.unpack('<L', byte_string)[0]
print(result)

Explanation:

  • struct.unpack is used to interpret the byte string.
  • '<L' specifies the format: < means little-endian (use > for big-endian), and L stands for an unsigned long (4 bytes).
  • This method is fast and directly converts the byte string into an integer.

Alternative with int.from_bytes (Python 3.x)

Another approach is to use int.from_bytes, which is even more direct and doesn't require importing any modules:

byte_string = b'y\xcc\xa6\xbb'
result = int.from_bytes(byte_string, byteorder='little')
print(result)

Explanation:

  • byteorder='little' means the bytes are in little-endian order (use byteorder='big' for big-endian).
  • This method is very simple and built into Python 3.x.

Performance

struct.unpack is very efficient for small byte strings, but int.from_bytes is also quite fast and easier to use. If you don't mind importing a module, struct.unpack works great, but if you want to avoid imports, int.from_bytes is a clean and modern alternative.