1

I am quite new to Python. I am trying to read an unformatted Fortran file by using Python. However, I would like to structure the elements read into arrays. I prepared for you a sample to help you understand my problem. Here below you can find a Fortran writer which writes three integers and then a line with three double precision elements.

    program writer
    integer :: dummy,dummy2,dummy3
    double precision,dimension(3) :: dummy_double
          dummy=1
          dummy2=2
          dummy3=3
          dummy_double(1)=4.23e0
          dummy_double(2)=5.4e0
          dummy_double(3)=7.61e0

          open(100,file="binary",form="unformatted",convert="little_endian")
          write(100) dummy
          write(100) dummy2
          write(100) dummy3
          write(100) dummy_double(1:3)
          close(100)
          end

I now want to read this file with Python without using numpy. I am aware of the INTEGER*4 at the end and beginning of each record. I skip the first 4 bits at the beginning of the file, then I read the first integer, then I skip 8 bits (end+begin) and so on. No separator is written in a same sequence, that is the double precision are not separated by an INTEGER*4 (correct me if I am wrong..). I am writing to you because I am not able to read the last line, with the 3 double precision records. I would like to store them in the comp[3] array.

import struct
with open("binary", "rb") as f:
#    while True:
        dummy = f.read(4)
        print "dummy=",struct.unpack('i', f.read(4))[0]
        dummy = f.read(8)
        print "dummy2=",struct.unpack('i', f.read(4))[0]
        dummy = f.read(8)
        print "dummy3=",struct.unpack('i', f.read(4))[0]
        comp = [0] * 3
        print "length=",len(comp)
        dummy = f.read(8)
        comp=struct.unpack('<d', f.read(8))[0:2]
        print "comp=",comp[0],comp[1],comp[2]

The error I am getting is the following:

$carlo: python Script_Library.py
dummy= 1
dummy2= 2
dummy3= 3
length= 3
comp= 4.23000001907
Traceback (most recent call last):
  File "Script_Library.py", line 14, in <module>
    print "comp=",comp[0],comp[1],comp[2]
IndexError: tuple index out of range

Integers are correctly read as well as the first double precision elements. However, they are not correctly stored. Would you please correct the parts of the script which are not working?

6
  • Which Fortran compiler do you use? 32-bit or 64-bit? The record markers are not that standardized as you appear to imply. Commented Feb 10, 2016 at 16:19
  • Try to replace the last line of your code with print "comp="+comp[0]+comp[1]+comp[2]. I guess the problem is that Python reads your code like (print "comp="), comp[0], comp[1], comp[2]. I'm not sure because I haven't write in Python2 for a long time and Python3 has different print syntax. But give it a try. Commented Feb 10, 2016 at 16:20
  • Also the line is not 3 double precision records but one record with 3 double precision numbers. Commented Feb 10, 2016 at 16:21
  • Thanks for your answer. I am using both ifort and gfortran 64 bits and the error message doesn't change. Commented Feb 10, 2016 at 16:22
  • 1
    Try to use comp=struct.unpack('<ddd', f.read(24)). comp will become a tuple with three numbers. struct.unpack() always returns tuple, even if there is only a single element. Commented Feb 10, 2016 at 21:34

2 Answers 2

2

the problem is solved thanks to durasm.

I report here the working codes:

program writer
integer :: dummy,dummy2,dummy3
double precision,dimension(3) :: dummy_double
          dummy=1
          dummy2=2
          dummy3=3
          dummy_double(1)=4.23e0
          dummy_double(2)=5.4e0
          dummy_double(3)=7.61e0

          open(100,file="binary",form="unformatted",convert="little_endian")
          write(100) dummy
          write(100) dummy2
          write(100) dummy3
          write(100) dummy_double(1:3)
          close(100)
end

Here below you can find the corrected script. First of all, no need to allocate comp. Then, we have three double precision records to read, equivalent to 24 bits and three times ddd.

import struct
with open("binary", "rb") as f:
        dummy = f.read(4)
        print "dummy=",struct.unpack('i', f.read(4))[0]
        dummy = f.read(8)
        print "dummy2=",struct.unpack('i', f.read(4))[0]
        dummy = f.read(8)
        print "dummy3=",struct.unpack('i', f.read(4))[0]
        dummy = f.read(8)
        comp=struct.unpack('<ddd', f.read(24))
        print "comp=",comp[0],comp[1],comp[2]

And the result:

$carlo: python Script_Library.py
dummy= 1
dummy2= 2
dummy3= 3
comp= 4.23000001907 5.40000009537 7.61000013351
Sign up to request clarification or add additional context in comments.

Comments

1

I think your problem is with this line:

comp=struct.unpack('<d', f.read(8))[0:2]

If you index a list with something [a:b] it will return a list of values from a to b-1:

>>> [1, 2, 3, 4][0:2]
[1, 2]

So after this line, comp is a list/array with two values, not three. So comp[2] will fail with an index out of range error.

1 Comment

Access='stream' is meant to be compatible with other languages.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.