O envio de entrada para shells / interpreters dessa forma é muito propenso a problemas e muito difícil de se trabalhar de maneira confiável.
A maneira correta é usar soquetes, é por isso que eles foram inventados, você pode fazer isso na linha de comando usando ncat nc ou socat para ligar um processo python a um soquete simples. Ou escreva um aplicativo python simples que se ligue à porta e escute os comandos para interpretar em um soquete.
sockets podem ser locais e não expostos a qualquer interface da web.
O problema é que se você iniciar python da linha de comando, ele normalmente é anexado ao seu shell que está anexado a um terminal, na verdade, podemos ver
$ ls -al /proc/PID/fd
lrwxrwxrwx 1 USER GROUP 0 Aug 1 00:00 0 -> /dev/pty1
assim, quando você escreve para stdin do python, você está realmente escrevendo para o pty psuedo-terminal, que é um dispositivo de kernel, não um arquivo simples. Ele usa ioctl não read e write , então você verá a saída na sua tela, mas ela não será enviada para o processo gerado ( python )
Uma maneira de replicar o que você está tentando é com um fifo ou 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
Você também pode usar screen somente para entrada
# start screen
$ screen -dmS python python
# send command to input
$ screen -S python -X 'print \"hello\"'
# view output
$ screen -S python -x