i'm actually wondering about python3's struct.pack behaviour, but maybe i missed something.
i'm submitting an .jpg file via UDP. Btw: the socket.sendTo() and sendAll() function throws a "Python IOError: [Errno 90] Message too long" when i try to submit the whole file (~200kB) at once. So i submit the file in pieces of 1024 bytes. No prob, i'm just wondering why i find nothing about this size-limitation in the python docs.
Anyway, my main issue is: i need struct.pack to put some information at the beginning of each piece -> 2 fixed-size strings.
but when i do
chunk = struct.pack("!3c4cI", bytes("JPG", "utf-8"), bytes(dev_id, "utf-8"), i)
it goes "struct.error: pack expected 8 items for packing (got 3)"
so i have to go
chunk = struct.pack("!3c4ci", b"J", b"P", b"G",
bytes(dev_id[0:1], "utf-8"),
bytes(dev_id[1:2], "utf-8"),
bytes(dev_id[2:3], "utf-8"),
bytes(dev_id[3:4], "utf-8"), i)
to make it work. Why is that!?
struct.packrequires that each item is passed as a separate argument. Additionally Python makes distinction betweencharandbyte, even though in C they're synonyms, that's why you need to have one-bytebytesvalues for thec, instead of integers in range 0 .. 255.However,
structalso supports thesformat specifier, wheresstands for a string of given length:Alternatively, if you're using at least Python 3.5, then thanks to PEP 448 -- Additional Unpacking Generalizations you can use the
B(unsigned byte) format in conjunction with splat operator*like this:What
*does here is to unpack every byte from the givenbytesvalue as an integer within range 0 ... 255 into separate arguments; ifdev_id.encode()results in 4 UTF-8 bytes, then a total of 8 arguments will be passed to thestruct.pack. And unlikec,Baccepts a single byte value as an integer.P.S. notice that I used
b'JPG'directly instead of callingbytes('JPG', 'UTF-8'), and likewise called.encode()on the string which encodes inUTF-8by default, for shorter code.