3

I'm trying to execute a Fortran program in a shell from Python. I'm using subprocess to call the Fortran program and pass arguments (two input files are required). This is how I do it:

COMMAND = '/path/to/FORTRAN/program << !\n' + INPUT_FILE1 + '\n' + INPUT_FILE2 +'\n!'
return = subprocess.call(COMMAND, shell=True)

Unfortunately, the Fortran program exits with:

? FORTRAN Runtime Error:
? Attempt to read past end of file
? READ(UNIT=22,...

This is not an issue with the input files or the Fortran program. When I execute this in my shell:

$>/path/to/FORTRAN/program << !
>INPUT_FILE1
>INPUT_FILE2
>!

everything works as expected (no Attempt to read past end of file).

I don't have access to the Fortran source, so I cannot check what is going on in there. I think it has to do with the way I'm calling the program through subprocess - I just can't figure out what.

I'm using Python 2.6.6.

Quick explanation: The Fortran program will prompt for two input files, but it doesn't recognize them as command-line options (they cannot be provided with the call to the program). If you want to run it from - say a shell script (batch mode) - you need to capture the return command to execute the command, but also provide the two files. The << ! opens a "list" for lack of a better term. The following commands are handed to the program which waits with its execution until ! is typed.

I have used this approach multiple times successfully (different Fortran code), and with this one, using a C shell script (not Python).

2
  • I don't know enough about running FORTRAN from a terminal - what's the significance of <<? Is that reading from stdin or otherwise? Perhaps the problem is that you're submitting the input files as arguments, but it expected a buffer it's going to parse. Hard to say without more info about the program in question. Commented Mar 28, 2013 at 21:06
  • I tried to reproduce by calling a small program that dumps its stdin, and both the command-line and subprocess work in this case. Commented Mar 28, 2013 at 21:50

3 Answers 3

1

You could try "\r\n" (tty newline):

from subprocess import Popen, PIPE

p = Popen(["/path/to/FORTRAN/program"], stdin=PIPE,
          bufsize=1, close_fds=True)
p.communicate("INPUT_FILE1\r\nINPUT_FILE2")
rc = p.returncode

with/without "\r\n" at the end.

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

3 Comments

this worked, with a slight modification: I used p.communicate("INPUT_FILE1\nINPUT_FILE2") without the \r. What is the difference between the communicate and the stdin.write, as suggested by @Armin-Rigo? Or is this rather a different question ...
In this case it should be equivalent to .stdin.close(); .wait(). The difference might be in the initial .write() part.
Though looking at the source I don't see any difference except bufsize=1 (line-buffered) and close_fds=True (the latter should be default on posix)
1

I had what may have been a similar problem a while back, and the solution turned out to be adding a small pause. Take a look at this and see whether that technique helps.

Comments

1

Maybe it's caused by the shell invoked with shell=True, if that doesn't invoke bash on your system. You can avoid depending on the extended shell syntax <<, and instead build the whole call on your own, as in:

popen = subprocess.Popen(["/path/to/FORTRAN/program"], stdin=subprocess.PIPE)
popen.stdin.write('123\n')
time.sleep(0.1)    # hack, following LAK's suggestion
popen.stdin.write('456\n')
popen.stdin.close()
result = popen.wait()

1 Comment

I've tried your updated proposal - and played with the sleep command a little - without success. For now I fixed it by writing the command to a shell script and executing that from Python. Maybe a bit convoluted, but it works.

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.