So this is what I would like to do: I have a double and I need to pack it into binary data and then get the upper four bytes and store them into a uint32 (it has to do with a device driver).
I already do this with floats:
import struct
import numpy as np
tmp = struct.pack('<f',float(datatobeconverted))
dataout = np.uint32(struct.unpack('<I',tmp))
I would like to do this with doubles but It doesn't seem to work:
tmp = struct.pack('<d',double(datatobeconverted))
dataout0 = np.uint32(struct.unpack('<I',tmp[0:3]))
dataout1 = np.uint32(struct.unpack('<I',tmp[4:7]))
Any ideas? By the way, I think the way struct stores binary data is unintuitive and hard to read
You're just slicing tmp
wrong.
>>> dataout0 = np.uint32(struct.unpack('<I',tmp[0:3]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
struct.error: unpack requires a string argument of length 4
>>>
The error message is pretty clear: the string arg you're passing is not "of length 4".
Python slices are always "right-bound excluded". So, to slice off the first 4 bytes, you do:
>>> dataout0 = np.uint32(struct.unpack('<I',tmp[:4]))
The 0:
in 0:4
is optional, and it's best to avoid it, as a matter of style, to minimize clutter (Tufte's "no wasted pixels" principle).
Similarly, to get everything but the first four bytes,
>>> dataout1 = np.uint32(struct.unpack('<I',tmp[4:]))
Left-bound is included, so you can use the same value (here, 4
) for both slicings (one of the advantage of the right-bound-excluded concept, helping you avoid off-by-one errors).
I first met this principle decades ago in Koenig's still-awesome book "C traps and pitfalls" and I have lived by it since -- and the principle's consistent adoption is part of what me love Python at first sight:-).
(I believe some kind of slicing on pandas
frames is the one exception to this principle throughout widespread Python libraries -- and part of why I can't get whole-heartedly into pandas
... but, that's another story!-).