1

Using Python, I want to execute an external program, interact with it by providing text to its standard input, and then print the result.

As an example, I created the following external program, called test.py:

print('Test Program')
print('1 First option, 2 Second Option')

choice = input()

if choice == '1':
    second_param = input('Insert second param: ')
    result = choice + ' ' + second_param
        
    print(result)

If I run this program directly, it works as expected. If I provide the input 1 and then 2, the output is 1 2.

I want to run this program from another script and interact with it to print the same result.

After reading the documentation for subprocess, I ended up with the following:

EXTERNAL_PROG = 'test.py'

p = Popen(['py', EXTERNAL_PROG], stdout=PIPE, stdin=PIPE, shell=True)

print(p.stdout.readline().decode('utf-8'))
print(p.stdout.readline().decode('utf-8'))
p.stdin.write(b'1\n')
p.stdin.write(b'2\n')
print(p.stdout.readline().decode('utf-8'))

However, when I run the code, the program freezes after printing 1 First option, 2 Second Option, and I need to restart my shell. This is probably caused by the fact that subprocess.stdout.readline() expects to find a newline character, and the prompt for the second param doesn’t contain one.


I found two related questions, but I still couldn’t get it to work.

Here, the answer recommends using the pexpect module. I tried to adapt the code to my situation, but it didn’t work.

Here, the suggestion is to use -u, but adding it didn’t change anything.


I know that a solution can be found by modifying test.py, but this is not possible in my case since I need to use another external program. This is just a minimal example based on it.

1
  • 1
    try changing the p.stdin.readline() commands to p.stdin.read(). You may even want to put it in a loop, as while (print(p.stdin.read())): next to ensure that anything that needs reading gets read. Not sure if that's the issue, but it will test your theory about the readline() functionality. Commented May 22, 2020 at 14:22

1 Answer 1

1

If you have fixed input to your program (means input not changing at run time) then this solution can be relevant.

Answer (Fixed Input)

First create file.

  • Input file. name it input.txt and put 1 2 in it

command = "python test.py < input.txt > output.txt 2>&1"

# now run this command

os.system(command)

When you run this, you will find output.txt in the same directory. If your program is executed successfully then output.txt contains the output of code test.py but if your code gives any error then error is in output.txt.

Answer (Variable Input)

Better solution where you can easily control input and output of external program/process.

main.py become

import sys
from subprocess import PIPE, Popen

EXTERNAL_PROG = 'test.py'

p = Popen(['python3', EXTERNAL_PROG], stdout=PIPE, stdin=PIPE, stderr=PIPE)

print(p.stdout.readline())
print(p.stdout.readline())
p.stdin.write(b'1\n')
p.stdin.write(b'2\n')
p.stdin.flush()
print(p.stdout.readline())
print(p.stdout.readline())
Sign up to request clarification or add additional context in comments.

12 Comments

This works if I have 1\n2 in input.txt. It's a great solution if the input is fixed.
Yeah Its because Your program is reading 2 integers separately. Your input file contains same data which you give to your program through console. If you got expected results Please Accept the answer
The only problem with this answer is that I don't want to have my input in a file. I want to pass it through the program itself. So let's say I have firstParam = 1, and secondParam = 2. Is there a way to use this as the input instead of reading from input.txt?
If your input is static (not changing runtime) then you can write it to file and then run above code but if your input is changing then it is not useful at all.
So let's say I have firstParam and secondParam as variables and I have calculated their values already. I can save their values into a file, run your code, and then delete the file. But is there a better way to do it, perhaps using a different command?
|

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.