Simon Rechermann
Simon Rechermann

Reputation: 501

python subprocess for user input

I want to get user input from a subprocess in an new terminal.

    import subprocess
    additionalBuildArguments = "defaultarg1"
    proc = subprocess.Popen(["python", "user_input.py", additionalBuildArguments],
                            creationflags=subprocess.CREATE_NEW_CONSOLE,
                            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    try:
        outs, errs = proc.communicate(timeout=15)
    except subprocess.TimeoutExpired:
        proc.kill()
        outs, errs = proc.communicate()
    additionalBuildArguments = outs or additionalBuildArguments

user_input.py:

import sys

arg = sys.argv[1]
user_input = input(f"Additional build arguments [{arg}] (Push <ENTER> to use these settings):\n")
print(user_input)

as long as I don't set the stdout=subprocess.PIPE and/or the stderr=subprocess.PIPE options I can enter input. But with these options I can't write any input to the console. Indeed I need these options to redirect the stdout, to have access to the printed user_input in the parent process. Does anyone know what's the problem here?

Upvotes: 0

Views: 1857

Answers (1)

2e0byo
2e0byo

Reputation: 5954

Please note that I do not understand why you want to do this, and feel instinctively that you should not. However, it's perfectly possible: just catpure only stdout:

import sys
from subprocess import run
print("Type away: ", end="")
sys.stdout.flush()
r = run(["python", "-c", "print(input())"], capture_output=True, encoding="utf8")
print(f"You entered {r.stdout}")

EDIT Apparently you are using windows. Per the docs your flag is set when shell=True. With shell=True this works for me, but I have no idea whether it will for you:

import sys
from subprocess import run
print("Type away: ", end="")
sys.stdout.flush()
r = run("python -c 'print(input())'", capture_output=True, shell=True, encoding="utf8")
print(f"You entered {r.stdout}")

This can be chained to run in yet a third process, which would be needed to print whilst also capturing stdout, from a subprocess. But at this point we are in the realm of very horrible hacks.

A better, but still hacky, solution, is to re-phrase the problem a bit. You want to spawn a terminal, which apparently you can do, and the user can interact with it correctly, and then you want to get output from that terminal in the spawning code. STDOUT is not the proper channel for this communication. Personally I would structure my code like this:

in spawning code:

  • generate parametrised script to run in spawned terminal and save it as a temp file
  • spawn subterminal running the generated script
  • wait for completion
  • read temp out file and get data
  • delete both temp script and temp out file

in generated code:

  • do as much as possible (you have a full python, after all)
  • dump output as json to a temporary file

This is still hacky, but it only involves spawning one terminal. Note that I still don't understand why you want to do this, but this should at least work.

Upvotes: 1

Related Questions