Reputation: 31
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?
Upvotes: 1
Views: 617
Reputation: 31
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
Upvotes: 2
Reputation: 8140
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.
Upvotes: 1