Using Python's subprocess and Popen in one scr

2019-02-13 09:35发布

问题:

The problem I have is as follows, and I will use simple example to illustrate it. I have written a python script that requires user interaction, specifically it uses the raw_input() function to get the user's input. The code below simply asks the user to type in two numbers in succession (hitting enter between each), and returns the answer (surprise, surprise, it is called 'sum_two_numbers.py'). Ho-hum!

#! /usr/bin/python

#  -------------------
#  sum_two_numbers.py
#  -------------------
#  This script asks the user for two numbers and returns the sum!

a = float(raw_input("Enter the first number:"))
b = float(raw_input("Enter the second number:"))

print a+b

Now, I want to write a separate python script that executes the above script and 'feeds' the two necessary numbers to it. I hence call this script 'feeder.py'. I tried to write this script using Python's 'subprocess' module, specifically using the 'Popen' class and its associated 'communicate' method. Below is the script trying to feed the numbers '5' and '4'.

#! /usr/bin/python

#  ----------
#  feeder.py
#  ----------
import subprocess

child = subprocess.Popen("./sum_two_numbers.py",stdin=subprocess.PIPE)

child.communicate("5")
child.communicate("4")

This code doesn't work, and returns the errors upon execution:

$ ./feeder.py
Enter the first number:Enter the second number:Traceback (most recent call last):
  File "./sum_two_numbers.py", line 6, in <module>
    b = float(raw_input("Enter the second number:"))
EOFError: EOF when reading a line
Traceback (most recent call last):
  File "./feeder.py", line 8, in <module>
    child.communicate("4")
  File "/usr/lib/python2.7/subprocess.py", line 740, in communicate
    self.stdin.write(input)
ValueError: I/O operation on closed file

I'm don't know how to write the 'feeder.py' so that it will do what I want, these errors keep hindering me. I suspect that this error arises because of the following comment in the documentation:

Popen.communicate(input=None)

Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate.

I'm not sure what to make of this sentence, and how it can help me...

Can anyone help me with making the above script work i.e. how to use subprocess and Popen properly... Or just how to write a 'feeder' script - in any (not too obscure) language! I have tried Pexpect, Expect but ran into problems like it not outputting the the child code's requests for input and me just generally having no idea what its doing.

回答1:

You can only call communicate once. Therefore you need to pass all the input at once, i.e. child.communicate("1\n1\n"). Alternatively you can write to stdin:

child = subprocess.Popen("./test.py", stdin=subprocess.PIPE)         

child.stdin.write("1\n")                                                       
child.stdin.write("1\n")