I am trying to translate a Perl script into Python.
I have some trouble translating this line:
my ($sync,$pid,$afccc,@bytes)=unpack('CnCC*',$pkt);
I tried this in Python
bytes=[]
sync,pid,afccc,bytes=struct.unpack_from('BHBB',pkt)
But the variable bytes is not a list after this line, then the execution fails.
FYI, pkt is a 188 chars long string.
There are two problems, only one of which was fixed in Python 3:
struct.unpack
doesn't support arbitrary repetition. (Python 3.4 introduced iter_unpack
, but that doesn't really help here.) You need an exact
count for each specifier. You can't write 'BHB*B'
; instead, you need to compute the number of bytes expected after BHB
. Fortunately, it's not that hard or ugly to do:
header_fmt = struct.Struct('BHB')
packet_fmt = struct.Struct(header_fmt.format +
'{}B'.format(188 - header_fmt.size))
# packet_fmt.format == 'BHB183B'
(In general you might need to use len(pkt)
instead of hardcoding 188.)
'BHB*B'
, though would be nice.
In Python 2, you have to extract the trailing bytes from the array explicitly:
fields = packet_fmt.unpack(pkt)
sync, pid, afccc = fields[3:]
bytes = fields[3:]
Alternatively, you can use unpack_from
and splicing, since you don't unpack bytes so much as you extract them.
sync, pid, afccc = header_fmt.unpack_from(pkt)
bytes = pkt[header_fmt.size:]
In Python 3, you can just use *name
syntax with tuple unpacking.
sync, pid, afccc, *bytes = packet_fmt.unpack(pkt)