How to escape from a hanging stdout.read() in REPL?

I run the following code in REPL and it hangs.

import subprocess
proc = subprocess.Popen(['python', 'temp.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
proc.stdin.write(b'hello')
proc.stdin.flush()
proc.stdout.read()
# it hangs

It runs under Windows 10, Python 3.12, and the temp.py content is “u = input(); print(u)”

In spite of the correctness of the temp.py, how to escape from this situation anyway?

One common way to handle this is Popen.communicate potentially with a timeout.

In general “read” without a size in CPython reads in a loop until it hits an “End Of File” marker (read returns size zero). input() is also a read and in specific a readline looking for a newline marker. If you add a \n to the proc.stdin.write(b'hello\n') it will find the newline and continue / exit (which would also likely eliminate the hang).

The input() blocking for more data + proc.stdout.read() blocking for more data is what gives the “hang” / “deadlock” you see here. Both processes are waiting for data from the other but never send any. communicate in its implementation works to ensure that the subprocess doesn’t block on I/O and waits for process exit. For this case, it will close proc.stdin which will result in the subprocess seeing an end of line / input() in temp.py to finish even without a \n.

This isn’t writing a newline. Maybe the subprocess is still waiting for end of line?

@Cody Maloney, @Chris Angelico, thank you for pointing out the missing b’\n’. What interested me is that once I was trapped into this situation by making a mistake, is there a way to escape from it instead of terminating the Windows cmd box?

1 Like

I’ve no idea! I would have thought that Ctrl-C should break out of that, but I can’t speak for Windows.

1 Like

Solved! Ctrl-Break works.

2 Likes