I found two alternatives to solve this problem.
- Using the
int.from_bytes(bytes, byteorder, *, signed=False)
method
- Using the
struct.unpack(format, buffer)
from the builtin struct
module
Using int.from_bytes
Starting from Python 3.2, you can use int.from_bytes
.
Second argument, byteorder, specifies endianness of your bytestring. It can be either 'big' or 'little'. You can also use sys.byteorder
to get your host machine's native byteorder.
from the docs:
The byteorder argument determines the byte order used to represent the integer. If byteorder is "big", the most significant byte is at the beginning of the byte array. If byteorder is "little", the most significant byte is at the end of the byte array. To request the native byte order of the host system, use sys.byteorder as the byte order value.
int.from_bytes(bytes, byteorder, *, signed=False)
Code applying in your case:
>>> import sys
>>> int.from_bytes(b'\x11', byteorder=sys.byteorder)
17
>>> bin(int.from_bytes(b'\x11', byteorder=sys.byteorder))
'0b10001'
Here is the official demonstrative code from the docs:
>>> int.from_bytes(b'\x00\x10', byteorder='big')
16
>>> int.from_bytes(b'\x00\x10', byteorder='little')
4096
>>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=True)
-1024
>>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=False)
64512
>>> int.from_bytes([255, 0, 0], byteorder='big')
16711680
Using the struct.unpack
method
The function you need to achieve your goal is struct.unpack
.
To understand where you can use it, we need to understand the parameters to give and their impact on the result.
struct.unpack(format, buffer)
Unpack from the buffer buffer (presumably packed by pack(format, ...)) according to the format string format. The result is a tuple even if it contains exactly one item. The buffer’s size in bytes must match the size required by the format, as reflected by calcsize().
The buffer is the bytes that we have to give and the format
is how the bytestring should be read.
The information will be split into a string, format characters, that can be endianness, ctype, bytesize, ecc..
from the docs:
Format characters have the following meaning; the conversion between C and Python values should be obvious given their types. The ‘Standard size’ column refers to the size of the packed value in bytes when using standard size; that is, when the format string starts with one of '<', '>', '!' or '='. When using native size, the size of the packed value is platform-dependent.
This table represents the format characters currently avaiable in Python 3.10.6:
Format |
C-Type |
Standard Size |
x |
pad byte |
|
c |
char |
1 |
b |
signed char |
1 |
B |
uchar |
1 |
? |
bool |
1 |
h |
short |
2 |
H |
ushort |
2 |
i |
int |
4 |
I |
uint |
4 |
l |
long |
4 |
L |
ulong |
4 |
q |
long long |
8 |
Q |
unsigned long long |
8 |
n |
ssize_t |
|
N |
unsigned ssize_t |
|
f |
float |
|
d |
double |
|
s |
char[] |
|
p |
char[] |
|
P |
void* |
|
and here is a table to use it to correct byte order:
Character |
Byte order |
Size |
Alignment |
@ |
native |
native |
Native |
= |
native |
standard |
None |
< |
little-endian |
standard |
None |
> |
big-endian |
standard |
None |
! |
network (= big-endian) |
standard |
None |
Examples
Here is an example how you can use it:
>>> import struct
>>> format_chars = '<i' #4 bytes, endianness is 'little'
>>> struct.unpack(format_chars,b"f|cs")
(1935899750,)