Schorsch
Schorsch

Reputation: 7915

Python subprocess not executing program correctly

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

Upvotes: 3

Views: 2012

Answers (3)

jfs
jfs

Reputation: 414795

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.

Upvotes: 1

Armin Rigo
Armin Rigo

Reputation: 12990

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()

Upvotes: 1

LAK
LAK

Reputation: 970

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.

Upvotes: 1

Related Questions