8

I am trying to talk to a device using python. I have been handed a tuple of bytes which contains the storage information. How can I convert the data into the correct values:

response = (0, 0, 117, 143, 6)

The first 4 values are a 32-bit int telling me how many bytes have been used and the last value is the percentage used.

I can access the tuple as response[0] but cannot see how I can get the first 4 values into the int I require.

6 Answers 6

13

Would,

num = (response[0] << 24) + (response[1] << 16) + (response[2] << 8) + response[3]

meet your needs?

aid

Sign up to request clarification or add additional context in comments.

1 Comment

when reading the above answers with importing modules, using loops and comprehensions for something as trivial as this, i really started scratching my head... this answer is actually how it is (and should be) done anywhere, and nothing will beat this in terms of speed and simplicity...
12

See Convert Bytes to Floating Point Numbers in Python

You probably want to use the struct module, e.g.

import struct

response = (0, 0, 117, 143, 6)
struct.unpack(">I", ''.join([chr(x) for x in response[:-1]]))

Assuming an unsigned int. There may be a better way to do the conversion to unpack, a list comprehension with join was just the first thing that I came up with.

EDIT: See also ΤΖΩΤΖΙΟΥ's comment on this answer regarding endianness as well.

EDIT #2: If you don't mind using the array module as well, here is an alternate method that obviates the need for a list comprehension. Thanks to @JimB for pointing out that unpack can operate on arrays as well.

import struct
from array import array

response = (0, 0, 117, 143, 6)
bytes = array('B', response[:-1])
struct.unpack('>I', bytes)

1 Comment

I would suggest that the pack format be ">I" i.e. big endian; 0x0000758f (30095₁₀) for a random count of bytes seems more likely than 0x8f750000 (2406809600₁₀)
4

OK, You don't specify the endinanness or whether the integer is signed or and it (perhaps) is faster to with the struct module but:

b = (8, 1, 0, 0)
sum(b[i] << (i * 8) for i in range(4))

2 Comments

just for reference this is for little-endian and can possibly be slightly improved as 'sum(b[i] << (i * 8) for i in range(len(b)))' to allow for variable size input or 'sum(response[i] << (i * 8) for i in range(len(response)-1))' for the OP.
@Ad__ I like this solution as it is probably faster than struct.unpack and unlike that method it doesn't require importing a module. Could you supply a version that would handle big-endian though please?
4

You could also make use of the array module

import struct
from array import array
response = (0, 0, 117, 143, 6)
a = array('B', response[:4])
struct.unpack('>I', a)

(30095L,)

3 Comments

I tried out this approach too, but decided to go with a list comprehension and join() instead, to avoid importing another module, and since neither was particularly clear, unfortunately.
I forgot that struct can pack arrays [fixed answer], which I think makes this version slightly better than the list comp.
Nice, I didn't know it could do that, missed that in the docs. I'll add it to my answer also as an alternate.
2

This looks like a job for reduce!

What you basically need is to, bit-shift a byte at a time, and then add (addition) the next byte in the sequence.

a = (0, 0, 117, 143, 6)
reduce(lambda x, y: (x<<8) + y, a)
7704326

4 Comments

-1 Read the question. There are FIVE bytes. The OP says the first 4 are a 32-bit int. The last is a percentage (6%).
@John: I think it's only a small mistake, just change in the second line a to a[:4] and the code works as needed by the OP (at least if big endian is intended). No need to downvote this directly.
@Kristian any chance of a version of this for little endian please?
@Caltor taking into consideration John's comment: reduce(lambda x, y: (x<<8) + y, a[:4][::-1])
0

How about using the map function:

a = (0, 0, 117, 143, 6)
b = []
map(b.append, a)

Also, I don't know if this is you are looking for:

response = (0, 0, 117, 143, 6)
response[0:4]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.