6

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?

2
  • 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). Commented Nov 7, 2012 at 16:39
  • 1
    never saw Fortran output like that Commented Nov 8, 2012 at 3:48

4 Answers 4

8

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 ...

Sign up to request clarification or add additional context in comments.

Comments

5

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) 

Comments

1

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] 

5 Comments

This is what I was going to do, but was wondering if someone had already done something like this. Obviously there would need to be more features of the library to merit a full library, but this is a bare minimum.
That function looks pretty good. It would require a minor modification as all of my numbers are formatted that way, not just the small ones.
What about negative numbers? -4.5000+1
better see if you have negs and how they are formatted -- its plausible they would run into the next number w/ no space, assuming a fixed field width.
-2

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) 

1 Comment

This "awk"ward answer unfortunately doesn't work. Using Python built-in functions like re.sub are usually more suitable.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.