BAMF4bacon
BAMF4bacon

Reputation: 593

python: struct pack size longer than expected -- why does this happen?

So I want to pack a list of tuples and then unpack it later.

from struct import *
from itertools import chain
a = [(1, 67), (213, 455), (9009, 8887)]
# converts 3x2 list to 6x1 list
b = list(chain(*a))   
size=6
qq = pack('h'+'L'*size,size,*b)
# peak to get the list length
mysize = unpack('h',qq[:2])  
mysize = mysize[0]
unpack('L',qq[2:6])    
unpack('h'+'L'*mysize,qq)
unpack('L'*mysize, qq[2:])   # does not work
unpack('L'*mysize, qq[2:2+mysize*4])  # works

Using Python 2.7, the second to last line does not work. I tested len(qq), which is 28, when I was expecting 26.

Upvotes: 0

Views: 305

Answers (1)

tdelaney
tdelaney

Reputation: 77337

According to the docs:

C types are represented in the machine’s native format and byte order, and properly aligned by skipping pad bytes if necessary (according to the rules used by the C compiler).

Since you are running on a 64 bit machine, smaller types such as h and L are padded to 8 bytes. You can use the formatting flags =, <, >, ! to remove the padding. For instance, adding "=" works

from struct import *
from itertools import chain
a = [(1, 67), (213, 455), (9009, 8887)]
# converts 3x2 list to 6x1 list
b = list(chain(*a))   
size=6
qq = pack('=h'+'L'*size,size,*b)
# peak to get the list length
mysize = unpack('=h',qq[:2])  
mysize = mysize[0]
unpack('=L',qq[2:6])    
unpack('=h'+'L'*mysize,qq)
unpack('=' + 'L'*mysize, qq[2:])   # does not work
unpack('=' + 'L'*mysize, qq[2:2+mysize*4])  # works

Upvotes: 1

Related Questions