2

I have a 3d party python script which takes input from the command line. The relevant code from this script (input.py) looks like the following:

import sys

def chooseinput():
    valid_inputs = ('a', 'b')
    inp = raw_input('Enter choice (%s): ' % "/".join(valid_inputs))
    if inp not in valid_inputs:
        sys.stderr.write("Unsupported input %s\n" % inp)
        return
    print 'You chose ' + '\'' + inp + '\''
    return inp

if __name__ == "__main__":
    chooseinput()
    # do something with the input...
    chooseinput()
    # do something with the input...

I'm trying to write another python script (harness.py) to generate the inputs for the above script.

import subprocess

def harness():
    p = subprocess.Popen(['python', 'input.py'], stdin=subprocess.PIPE)
    p.stdin.write('a')
    p.stdin.write('b')

if __name__ == '__main__':
    harness()

From the command line, I run:

$ python harness.py
Enter choice (a/b): Enter choice (a/b): Traceback (most recent call last):
  File "input.py", line 13, in <module>
    chooseinput()
  File "input.py", line 5, in chooseinput
    inp = raw_input('Enter choice (%s): ' % "/".join(valid_inputs))
EOFError: EOF when reading a line

If I only have one input in the first script, then I can make the second script work by removing the second write call. If the first script requires more than one input, then I get the above error.

Ravi
  • 3,718
  • 7
  • 39
  • 57

3 Answers3

6

Try:

p.stdin.write('a\n')
p.stdin.write('b\n')
linuts
  • 6,608
  • 4
  • 35
  • 37
4

linuts answer works well in your simple example, but for the benefit of future readers, I would strongly recommend against using this methodology for communicating between Python scripts.

This method is a throwback to when few other options were available. Pexpect, bless its heart, may indeed be a good program, but it merely puts a happy face on a miserable interface technique. Command-line control such as this is often timing dependent, quickly making it tedious and error-prone. Use it only when you have no other choice.

Python brings many much more powerful methods to scripting. Unless you don't have access to script internals (with Python, you almost always do) you should instead write your harness.py script to import the 3-party script as a library and control it programmatically by calling its methods/functions directly.

Your current predicament may not allow it, but with Python scripts, command-line communication should be the last choice, not the first.

JS.
  • 14,781
  • 13
  • 63
  • 75
  • @JS makes an excellent point, if you have a python module whose functionality you want to utilize your first choice should be to import that module. One of the great features of python is how easy it is to import and utilize another python module's classes/objects/functions--even if the module wasn't built with this functionality in mind. Command line communication should be a last resort. – Chris W. May 24 '11 at 17:39
2

You should check out Pexpect.

Pexpect is a pure Python module for spawning child applications; controlling them; and responding to expected patterns in their output. The child application can be any executable (for instance, as in your case, another python script). It works similarly to the unix tool "expect".

Chris W.
  • 37,583
  • 36
  • 99
  • 136