9
import subprocess

child = subprocess.Popen(['python', 'simple.py'], stdin=subprocess.PIPE)
child.communicate('Alice')

I know you can communicate with executed script via communicate How do you check for whether a script 'simple.py' is asking for user input?

simple.py could ask for 5-10 user inputs so simply hardcoding communicate wouldnt be enough.

[EDIT]: want to parse the stdout as the script is running and communicate back to the script

while True:
    if child.get_stdout() == '?':
       # send user input
ealeon
  • 12,074
  • 24
  • 92
  • 173
  • 1
    You can't. Programs don't ask for input; they wait for it. – zondo Mar 02 '16 at 15:23
  • how do i know if they are waiting for it.... (ask/wait) i dont see the difference – ealeon Mar 02 '16 at 15:24
  • 1
    You just can't. When it is waiting for input, it is just doing nothing until it gets it. There are many reasons for doing nothing, so there is no way to know that it is waiting specifically for input. – zondo Mar 02 '16 at 15:26
  • well i know at what stdout it is waiting for user input. how do i get stdout as the script prints out then? – ealeon Mar 02 '16 at 15:30
  • @zondo i want to be able to do something like the edited section – ealeon Mar 02 '16 at 15:31
  • You might find the [pexpect](https://pexpect.readthedocs.org/en/stable/) module useful. – zondo Mar 02 '16 at 15:32
  • You would have to write to stdin and parse from stdout – Padraic Cunningham Mar 02 '16 at 15:34
  • 1
    You can check the waiting channel in `/proc//wchan` or you can trace the subprocess with `ptrace`/`strace`/whatever you like. – Andrea Corbellini Mar 02 '16 at 15:45
  • here's [code example for a "dialog-based interaction" with a child process using `subprocess` and `pexpect`](http://stackoverflow.com/q/7897202/4279). You should try to import the module instead of running it as a subprocess: put the code into functions and call them in the parent, [example](http://stackoverflow.com/q/30076185/4279) – jfs Mar 02 '16 at 19:41

1 Answers1

2

A simple example:

simple.py:

i = raw_input("what is your name\n")
print(i)
j = raw_input("What is your age\n")
print(j)

Read and write:

import subprocess

child = subprocess.Popen(['python2', 'simple.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

for line in iter(child.stdout.readline, ""):
    print(line)
    if "name" in line:
        child.stdin.write("foo\n")
    elif "age" in line:
        child.stdin.write("100\n")

Output:

what is your name

foo

What is your age

100
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • 1
    Thank you! This is what I am looking for – ealeon Mar 02 '16 at 19:52
  • 2
    @ealeon: beware, unless you know exactly how much you should write/read; it is very easy to hang the child process if input/output are out-of-sync (If you try to read too much; you may wait indefinitely for an input that will never come or if you try to write too much then as soon as the corresponding OS pipe buffers are full the `write`s may block). In general, you should use threads or async. I/O if you are handling more than one pipe (as in this case). – jfs Mar 03 '16 at 12:15
  • @jfs could you elaborate? Is your comment particularly in the context of the sample code above, being that the child may be waiting for input but won't receive it because the parent loop impacts it somehow? Or is there something else that can "getcha" when using both `stdin` and `stdout` pipes together? – Michael Harris May 17 '23 at 15:54
  • 1
    @MichaelHarris: my comment is about the general approach (plus/minus unrelated block-buffering issues, the code in the answer may work). Here's code that demonstrate what happens if read/writing are not synchronized perfectly and synchronous read/write are used https://gist.github.com/zed/dc609d81ce72b3ec9a5619ff0262d889 – jfs Jun 03 '23 at 11:08