You can’t block on reads. You should perform non-blocking reads in a separate thread, and only have the write in the main thread. Also, you should send keyboard interrupts through to the subprocess
Start the Python subprocess with the -i flag. When it starts, it’ll print the banner to stderr.
You won’t get anything coming back on stdout until the Python subprocess prints to stdout.
process = start(["python", "-i"])
write(process, "message = 'Hello world!'")
# Nothing printed to stdout yet.
write(process, "print(message)")
# Now there's something you can read.
read(process)
As mentioned above by Matthew, you’ll need to run Python in interactive mode. If you don’t force interactive mode, the interpreter reads from stdin until the pipe closes, and only then does it compile and execute the input script. Also, without interactive mode the interpreter buffers standard output to a pipe. If buffering is enabled, it won’t actually flush writes to the pipe until the buffer is full.
Be aware that reading from separate stdout and stderr pipes may deadlock. For example, the parent is blocked reading from an empty stdout pipe, while the child is blocked writing to a full stderr pipe. The simplest approach to avoid deadlock that works cross-platform is to use separate reader threads for stdout and stderr, with separate queue.Queue() FIFOs.
Also, run the child interpreter with UTF-8 mode enabled (e.g. -X utf8 command-line option), or at least with PYTHONIOENCODING set to “UTF-8” for sys.std*. Otherwise the interpreter may use a legacy encoding for standard I/O. For example, on Windows Python uses the ANSI code page of the process for non-console I/O, which is usually a legacy encoding such as code page 1252.