Reputation: 187
I'm trying to use Python to automate a process that involves calling a Fortran executable and submitting some user inputs. I've spent a few hours reading through similar questions and trying different things, but haven't had any luck. Here is a minimal example to show what I tried last
#!/usr/bin/python
import subprocess
# Calling executable
ps = subprocess.Popen('fortranExecutable',shell=True,stdin=subprocess.PIPE)
ps.communicate('argument 1')
ps.communicate('argument 2')
However, when I try to run this, I get the following error:
File "gridGen.py", line 216, in <module>
ps.communicate(outputName)
File "/opt/apps/python/epd/7.2.2/lib/python2.7/subprocess.py", line 737, in communicate
self.stdin.write(input)
ValueError: I/O operation on closed file
Any suggestions or pointers are greatly appreciated.
EDIT:
When I call the Fortran executable, it asks for user input as follows:
fortranExecutable
Enter name of input file: 'this is where I want to put argument 1'
Enter name of output file: 'this is where I want to put argument 2'
Somehow, I need to run the executable, wait until it asks for user input and then supply that input.
Upvotes: 9
Views: 23396
Reputation: 414315
If the input doesn't depend on the previous answers then you could pass them all at once using .communicate()
:
import os
from subprocess import Popen, PIPE
p = Popen('fortranExecutable', stdin=PIPE) #NOTE: no shell=True here
p.communicate(os.linesep.join(["input 1", "input 2"]))
.communicate()
waits for process to terminate therefore you may call it at most once.
Upvotes: 8
Reputation: 4318
By the time, you reach ps.communicate('argument 2'), ps process is already closed as ps.communicate('argument 1') waits until EOF. I think, if you want to write multiple times at stdin, you might have to use:
ps.stdin.write('argument 1')
ps.stdin.write('argument 2')
Upvotes: 0
Reputation: 1394
your arguments should not be passed to communicate. they should be given in the call to Popen, like: http://docs.python.org/2/library/subprocess.html#subprocess.Popen
>>> import shlex, subprocess
>>> command_line = raw_input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print args
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args) # Success!
Upvotes: -1