I would like to pack all the data in a list into a single buffer to send over a UDP socket. The list is relatively long, so indexing each element in the list is tedious. This is what I have so far:
NumElements = len(data)
buf = struct.pack('d'*NumElements,data[0],data[1],data[2],data[3],data[4])
But I would like to do something more pythonic that doesn't require I change the call if I added more elements to the list... something like:
NumElements = len(data)
buf = struct.pack('d'*NumElements,data) # Returns error
Is there a good way of doing this??
Yes, you can use the *args
calling syntax.
Instead of this:
buf = struct.pack('d'*NumElements,data) # Returns error
… do this:
buf = struct.pack('d'*NumElements, *data) # Works
See Unpacking Argument Lists in the tutorial. (But really, read all of section 4.7, not just 4.7.4, or you won't know what "The reverse situation…" is referring to…) Briefly:
… when the arguments are already in a list or tuple but need to be unpacked for a function call requiring separate positional arguments… write the function call with the *-operator to unpack the arguments out of a list or tuple…
The format string for struct.pack(...)
and struct.unpack(...)
allows to pass number(representing count) in front of type, with meaning how many times is the specific type expected to be present in the serialised data:
Simple case
data = [1.2, 3.4, 5.6]
struct.pack('3d', data[0], data[1], data[2])
struct.pack('3d', *[1.2, 3.4, 5.6])
or more generally:
data = [1.0, 1.234, 1.9, 3.14, 6.002, 7.4, 9.2]
struct.pack('{}d'.format(len(data)), *data)