Eryk Sun <[email protected]> added the comment:
Interactive mode isn't automatically enabled when stdin isn't a tty, so the
interpreter tries to read all of stdin, until the result is empty (i.e. EOF).
You can force interactive mode with the -i command-line option. The example
would also benefit from passing bufsize=0 to Popen, since full buffering on
either the child side or parent side of the pipe prevents interactive I/O.
Finally, input statements have to end with a newline character since the
interpreter reads input in lines.
Here's a toy example that interacts with a REPL in a child process. Note that
spawn_repl() sets the sys.ps1 prompt in the child to a string that ends with a
newline. This allows iterating over the lines in p.stdout up to the REPL
prompt. Also, spawn_repl() forces UTF-8 mode in order to reliably support
Unicode. Otherwise text support in Windows is limited to the ANSI code page.
import subprocess
def _write_input(p, input):
if not input.endswith('\n'):
input += '\n'
p.stdin.write(input)
def _read_output(p):
lines = []
for line in p.stdout:
if line.endswith(p._ps1):
break
lines.append(line)
return lines
def eval_remote(p, input):
if not hasattr(p, '_ps1'):
raise ValueError('p._ps1 prompt not defined; use p = spawn_repl()')
_write_input(p, input)
return _read_output(p)
def spawn_repl():
p = subprocess.Popen(
['python', '-i', '-q', '-X utf8'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=0, encoding='utf-8')
p._ps1 = f'<PY:{p.pid}>\n'
eval_remote(p, f'import sys; sys.ps1="<PY:{p.pid}>\\n"')
return p
For example:
>>> p = spawn_repl()
>>> eval_remote(p, 'double = lambda x: 2 * x')
[]
>>> eval_remote(p, 'double(2)')
['4\n']
>>> eval_remote(p, 'print("spam\\neggs")')
['spam\n', 'eggs\n']
----------
nosy: +eryksun
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue45719>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com