[英]Python read from subprocess stdout and stderr separately while preserving order
[英]Python: program hangs when trying to read from subprocess stdout while it is running
我正在尝试使用 python 子进程模块与 c++ 脚本(我们称之为脚本 A)进行通信。 脚本 A 与 python 程序一起运行并不断与之交互。 我的目标是发送脚本 A 输入命令,然后捕获脚本 A 打印到 STDOUT 的输出。我正在研究 windows 10。
这是描述逻辑的片段:
proc = subprocess.Popen([".\\build\\bin.exe"], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
terminate = False
while not terminate:
command = input("Enter your command here: ")
if command == "q":
terminate = True
else:
proc.stdin.write(command.encode()) # send input to script A
output = proc.stdout.readline().decode() # problematic line, trying to capture output from script A
print(f"Output is: {output}")
问题是,虽然脚本 A 在每个命令之后像我期望的那样将 output 写入 STDOUT,但 python 脚本在到达上面突出显示的行时会挂起。 我尝试在调用 Popen 和for line in iter(proc.stdout.readlines())
时使用proc.stdout.read(1)
和bufsize=0
捕获 output 和其他一些方法,但问题仍然存在。
将不胜感激这方面的任何帮助,因为我没有尝试过对我有用。 提前致谢!
您已经建议使用bufsize=0
,这似乎是正确的解决方案。 但是,这只影响 Python 端的缓冲。 如果您正在调用的可执行文件使用缓冲输入或 output,我认为您无能为力(也如此处所述)。
如果这两个程序都在您自己的控制之下,那么您可以轻松地完成这项工作。 这是一个例子。 为简单起见,我创建了两个 Python 脚本,它们以类似的方式相互交互。 请注意,这与 C++ 应用程序的情况没有太大区别,因为在这两种情况下,可执行文件都作为子进程启动。
文件pong.py
(读取输入并响应它的简单演示应用程序 - 类似于您的“脚本 A”):
while True:
try:
line = input()
except EOFError:
print('EOF')
break
if line == 'ping':
print('pong')
elif line == 'PING':
print('PONG')
elif line in ['exit', 'EXIT', 'quit', 'QUIT']:
break
else:
print('what?')
print('BYE!')
文件main.py
(与pong.py
通信的主程序):
import subprocess
class Test:
def __init__(self):
self.proc = subprocess.Popen(['python.exe', 'pong.py'], bufsize=0, encoding='ascii',
stdout=subprocess.PIPE, stdin=subprocess.PIPE)
def talk(self, tx):
print('TX: ' + tx)
self.proc.stdin.write(tx + '\n')
rx = self.proc.stdout.readline().rstrip('\r\n')
print('RX: ' + rx)
def main():
test = Test()
test.talk('ping')
test.talk('test')
test.talk('PING')
test.talk('exit')
if __name__ == '__main__':
main()
python main.py 的python main.py
:
TX: ping
RX: pong
TX: test
RX: what?
TX: PING
RX: PONG
TX: exit
RX: BYE!
当然还有其他解决方案。 例如,您可以使用套接字在两个应用程序之间进行通信。 但是,这仅适用于您可以修改两个应用程序(例如,如果您正在开发两个应用程序),而不是当您调用的可执行文件是第三方应用程序时。
首先, buffersize=0
,这是正确的解决方案。 然而,这还不够。
在您的可执行程序中,您应该将标准输出缓冲区大小设置为 0。或及时刷新。
在 C/C++ 程序中,您可以添加
setbuf(stdout, nullptr);
到您的源代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.