Python 子进程交互被 stdout.readline() 阻止
Python subprocess interaction blocked by stdout.readline()
我正在尝试使用 subprocess 模块启动另一个 Pyhton 实例,发送命令并检索输出。但是无论我尝试什么,它总是挂在 stdout.readline()
。这是我目前的尝试:
from subprocess import Popen, PIPE, STDOUT
script = "import sys;sys.stdout.write('glorp')\n"
p = Popen([r"C:\Program Files\Python37\python.exe",], stdin=PIPE, stdout=PIPE, text=True)
p.stdin.write(script)
print("readline")
print(p.stdout.readline())
print("end")
代码永远不会超过涉及 readline()
的行。我试过在 stdin
和 stdout
.
上使用 flush()
这里的主要问题是 Python 解释器在我们作为子进程启动时没有处于交互模式。正如 Python documentation 注释:
When called with standard input connected to a tty device, it prompts for commands and executes them
在这种情况下,子进程的 stdin
没有连接到终端(“tty 设备”)。并且
In non-interactive mode, the entire input is parsed before it is executed.
所以 Python 只是坐在那里什么都不做,直到 stdin
关闭。但是我们可以用 -i
command-line option 强制它进入交互模式。那么:
When a script is passed as first argument or the -c
option is used, enter interactive mode after executing the script or the command, even when sys.stdin
does not appear to be a terminal.
传递 -q
option
也很有用
Don’t display the copyright and version messages even in interactive mode.
并通过设置bufsize=0
以非缓冲模式与子进程通信。然后我们可以让解释器 运行 多个命令,我们可以检查中间的输出:
from subprocess import Popen, PIPE
p = Popen(['python', '-i', '-q'], stdin=PIPE, stdout=PIPE, text=True, bufsize=0)
p.stdin.write('print("First line executed.")\n')
print(p.stdout.readline(), end='')
p.stdin.write('print("Second line executed.")\n')
print(p.stdout.readline(), end='')
请注意,控制台中的提示 (>>>
) 可能出现乱序:
>>> >>> First line executed.
Second line executed.
>>>
我们可以通过在启动解释器时将 '-c', 'import sys; sys.ps1=""'
添加到参数列表来隐藏 V 形符号。
还建议在两端明确设置编码为UTF-8。在 Python 错误跟踪器上的 this issue 中可以找到更详尽的演示。
我正在尝试使用 subprocess 模块启动另一个 Pyhton 实例,发送命令并检索输出。但是无论我尝试什么,它总是挂在 stdout.readline()
。这是我目前的尝试:
from subprocess import Popen, PIPE, STDOUT
script = "import sys;sys.stdout.write('glorp')\n"
p = Popen([r"C:\Program Files\Python37\python.exe",], stdin=PIPE, stdout=PIPE, text=True)
p.stdin.write(script)
print("readline")
print(p.stdout.readline())
print("end")
代码永远不会超过涉及 readline()
的行。我试过在 stdin
和 stdout
.
flush()
这里的主要问题是 Python 解释器在我们作为子进程启动时没有处于交互模式。正如 Python documentation 注释:
When called with standard input connected to a tty device, it prompts for commands and executes them
在这种情况下,子进程的 stdin
没有连接到终端(“tty 设备”)。并且
In non-interactive mode, the entire input is parsed before it is executed.
所以 Python 只是坐在那里什么都不做,直到 stdin
关闭。但是我们可以用 -i
command-line option 强制它进入交互模式。那么:
When a script is passed as first argument or the
-c
option is used, enter interactive mode after executing the script or the command, even whensys.stdin
does not appear to be a terminal.
传递 -q
option
Don’t display the copyright and version messages even in interactive mode.
并通过设置bufsize=0
以非缓冲模式与子进程通信。然后我们可以让解释器 运行 多个命令,我们可以检查中间的输出:
from subprocess import Popen, PIPE
p = Popen(['python', '-i', '-q'], stdin=PIPE, stdout=PIPE, text=True, bufsize=0)
p.stdin.write('print("First line executed.")\n')
print(p.stdout.readline(), end='')
p.stdin.write('print("Second line executed.")\n')
print(p.stdout.readline(), end='')
请注意,控制台中的提示 (>>>
) 可能出现乱序:
>>> >>> First line executed.
Second line executed.
>>>
我们可以通过在启动解释器时将 '-c', 'import sys; sys.ps1=""'
添加到参数列表来隐藏 V 形符号。
还建议在两端明确设置编码为UTF-8。在 Python 错误跟踪器上的 this issue 中可以找到更详尽的演示。