Sending input to shells/interpreters in this way is very problem-prone and very difficult to get working in any reliable way.
The proper way is to use sockets, this is why they were invented, you can do this in command line using ncat
nc
or socat
to bind a python process to a simple socket. Or write a simple python application that binds to port and listens for commands to interpret on a socket.
sockets can be local and not exposed to any web interface.
The problem is that if you start python
from the command line, it is typically attached to your shell which is attached to a terminal, in fact we can see
$ ls -al /proc/PID/fd
lrwxrwxrwx 1 USER GROUP 0 Aug 1 00:00 0 -> /dev/pty1
so when you write to stdin
of python, you are actually writing to the pty
psuedo-terminal, which is a kernel device, not a simple file. It uses ioctl
not read
and write
, so you will see output on your screen, but it will not be sent to the spawned process (python
)
One way to replicate what you are trying is with a fifo
or named pipe
.
# make pipe
$ mkfifo python_i.pipe
# start python interactive with pipe input
# Will print to pty output unless redirected
$ python -i < python_i.pipe &
# keep pipe open
$ sleep infinity > python_i.pipe &
# interact with the interpreter
$ echo "print \"hello\"" >> python_i.pipe
You can also use screen
for input only
# start screen
$ screen -dmS python python
# send command to input
$ screen -S python -X 'print \"hello\"'
# view output
$ screen -S python -x