Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python subprocess stdout doesn't capture input prompt

I'm using subprocess to spawn a conda create command and capture the resulting stdout for later use. I also immediately print the stdout to the console so the user can still see the progress of the subprocess:

p = subprocess.Popen('conda create -n env1 python', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
    sys.stdout.write(line.decode(sys.stdout.encoding))

This works fine until half way through the execution when the conda create requires user input: it prompts Proceed (n/y)? and waits for the user to input an option. However, the code above doesn't print the prompt and instead just waits for input "on a blank screen". Once an input is received the prompt is printed afterwards and then execution continues as expected.

I assume this is because the input somehow blocks the prompt being written to stdout and so the readline doesn't receive new data until after the input block has been lifted.

Is there a way I can ensure the input prompt is printed before the subprocess waits for user input? Note I'm running on Windows.

like image 336
Mrfence Avatar asked Sep 16 '25 06:09

Mrfence


1 Answers

Although I'm sure pexpect would have worked in this case, I decided it would be overkill. Instead I used MisterMiyagi's insight and replaced readline with read.

The final code is as so:

p = subprocess.Popen('conda create -n env1 python', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while p.poll() is None:
    sys.stdout.write(p.stdout.read(1).decode(sys.stdout.encoding))
    sys.stdout.flush()

Note the read(1) as just using read() would block the while loop until an EOF is found. Given no EOF is found before the input prompt, nothing will be printed at all! In addition, flush is called which ensures the text written to sys.stdout is actually visible on screen.

like image 168
Mrfence Avatar answered Sep 17 '25 18:09

Mrfence