Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python struct.pack() for individual elements in a list?

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??

like image 663
user1636547 Avatar asked May 03 '13 22:05

user1636547


2 Answers

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)
like image 78
PeterB Avatar answered Sep 27 '22 20:09

PeterB


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…

like image 27
abarnert Avatar answered Sep 27 '22 20:09

abarnert