Gerard
Gerard

Reputation: 2860

Python struct.error: unpack requires a string argument of length 2

I have written some data using C++ in byte format. I am now trying to read that data again using Python, but I run into an error;

Traceback (most recent call last):
  File "binary-reader.py", line 61, in <module>
    interaction_types.append(struct.unpack('<H',fp.read(2))[0]);
struct.error: unpack requires a string argument of length 2

I don't really understand since it looks like I am giving a string of length 2, right? Furthermore, I do the same thing at line 32

There is another question like mine but it is without an answer is targeted for Python 3.

Here is my code

import sys
import struct
import os

print "Arguments : "
print str(sys.argv)

#N = #isects

#  2      2        3*4      2          3*4*N          4N            4N      3*4N        2N          2N
#imageX,imageY,throughput,#isects,isect_positions,primitive_ids,shape_ids,spectra,interaction_types,light_ids
file_path = str(sys.argv[1]);

byte_count = 0;
line_number = 1;

fp = open(file_path, "rb");
output = open('output.txt',"w");
file_size = os.path.getsize(file_path)

print "(input) file size = " + str(file_size);

while byte_count < file_size:
    print "Line number = " + str(line_number)
    print "Current byte count = " + str(byte_count)
    # Do stuff with byte.
    x = struct.unpack('<H', fp.read(2))[0]
    y = struct.unpack('<H', fp.read(2))[0]
    throughputOne = struct.unpack('<f', fp.read(4))[0]
    throughputTwo = struct.unpack('<f', fp.read(4))[0]
    throughputThree = struct.unpack('<f', fp.read(4))[0]
    nrIsects = struct.unpack('<H',fp.read(2))[0]

    # print "x = " + str(x)
    # print "y = " + str(y)
    # print "throughputOne = " + str(throughputOne)
    # print "throughputTwo = " + str(throughputTwo)
    # print "throughputThree = " + str(throughputThree)
    print "nrIsects = " + str(nrIsects)

    isect_positions = []
    for i in range(nrIsects*3):
        value = struct.unpack('<f',fp.read(4))[0]
        isect_positions.append(value);

    primitive_ids = []
    for i in range(nrIsects):
        value = struct.unpack('<I',fp.read(4))[0]
        primitive_ids.append(value);

    shape_ids = []
    for i in range(nrIsects):
        shape_ids.append(struct.unpack('<I',fp.read(4))[0]);

    spectra = []
    for i in range(nrIsects*3):
        spectra.append(struct.unpack('<f',fp.read(4))[0]);

    interaction_types = []
    for i in range(nrIsects):
        interaction_types.append(struct.unpack('<H',fp.read(2))[0]);

    light_ids = []
    for i in range(nrIsects):
        light_ids.append(struct.unpack('<H',fp.read(2))[0]);

    output_vars = [x,y,throughputOne,throughputTwo,throughputThree,nrIsects]

    line_string = ""

    for i in range(len(output_vars)):
        output.write(str(output_vars[i]))
        line_string += str(output_vars[i])
        if i is not len(output_vars) - 1:
            output.write(',')   
            line_string += ','

    print line_string


    #Update counters
    byte_count += 18 + 36*nrIsects
    line_number+=1

    # raw_input('Press any key to continue.');

    # print byte

And here is a link to a input file to use. You can run the code by passing a commandline argument specifying the path of the binary file. I have also written the code in ASCII, which reads

0,0,[0.127076,0.127076,0.127076],1,{[0.144978,-0.294863,2.991749]},{3917},{3916},{[1.375603,1.375603,1.375603]},{5},{0}

https://www.dropbox.com/s/tu1anqo5k0ygtd6/writetest.bin

EDIT: The layout of my file can be found as a comment in the code

Upvotes: 3

Views: 20726

Answers (1)

unutbu
unutbu

Reputation: 879481

50 bytes have already been read before the fp.read(2) that raises the error. Thus, fp.read(2) returns an empty string, and struct.unpack raises an exception:

In [83]: 2+2+4+4+4+2+12+4+4+12
Out[83]: 50

x = struct.unpack('<H', fp.read(2))[0]                  # 2 bytes read
y = struct.unpack('<H', fp.read(2))[0]                  # 2 bytes
throughputOne = struct.unpack('<f', fp.read(4))[0]      # 4 bytes
throughputTwo = struct.unpack('<f', fp.read(4))[0]      # 4 bytes
throughputThree = struct.unpack('<f', fp.read(4))[0]    # 4 bytes
nrIsects = struct.unpack('<H',fp.read(2))[0]            # 2 bytes

print "nrIsects = " + str(nrIsects)

isect_positions = []
for i in range(nrIsects*3):
    value = struct.unpack('<f',fp.read(4))[0]           # 12 bytes
    isect_positions.append(value)

primitive_ids = []
for i in range(nrIsects):
    value = struct.unpack('<I',fp.read(4))[0]           # 4 bytes
    primitive_ids.append(value)

shape_ids = []
for i in range(nrIsects):
    shape_ids.append(struct.unpack('<I',fp.read(4))[0]) # 4 bytes

spectra = []
for i in range(nrIsects*3):
    spectra.append(struct.unpack('<f',fp.read(4))[0])   # 12 bytes

interaction_types = []
for i in range(nrIsects):
    interaction_types.append(struct.unpack('<H', fp.read(2))[0])   # error!

Upvotes: 2

Related Questions