5
votes

I have to read a data file that contains numbers formatted with (very) old FORTRAN style. A line of the file looks like this:

 4.500000+1 1.894719-3 4.600000+1 8.196721-3 4.700000+1 2.869539-3

The file (or large portion of it) contains these numbers in a fixed width format. The trouble with reading these numbers in Python is that there is no E in these numbers. Watch what happens:

>>> float('4.50000+1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for float(): 4.50000+1

I can write a parser to read this, but wanted to know if this has already be done. This is an old FORTRAN format so I thought perhaps someone had already figured it out. Does anyone know of a library to read numbers like this?

4
The simplest is probably to insert an E before the + or - and the Python have at the resulting string. (Assuming that's what it actually means). - hmakholm left over Monica
never saw Fortran output like that - agentp

4 Answers

2
votes

this should work:

In [47]: strs="4.500000+1 1.894719-3 4.600000+1 8.196721-3 4.700000+1 2.869539-3"

In [48]: [float(x.replace("+","e+").replace("-","e-")) for x in strs.split()]

Out[48]: [45.0, 0.001894719, 46.0, 0.008196721, 47.0, 0.002869539]
8
votes

You could use the Fortran Format Library for Python as follows,

>>> import fortranformat as ff
>>> reader = ff.FortranRecordReader('(6F13.7)')
>>> reader.read(' 4.500000+1 1.894719-3 4.600000+1 8.196721-3 4.700000+1 2.869539-3')
[45.0, 0.001894719, 46.0, 0.008196721, 47.0, 0.002869539]

This library has been extensively tested aginst Intel's ifort 9.1 compiler to match exactly some of the weirder FORTRAN textual IO.

Install using

pip install fortranformat

I should declare a bias since I wrote this library ...

5
votes

You could use a regular expression to insert the "E"s before passing the numbers to float.

re.sub(r'(\d)([-+])', r'\1E\2', number)
0
votes

Another approach is to use a system command to access AWK:

Note the escaping of the " characters inside COMMAND

import subprocess
COMMAND = "awk 'gsub(/D/,\"E\");{print}' epsc8.out > epsc8E.out"
subprocess.call(COMMAND, shell=True)