繁体   English   中英

Python:程序在运行时尝试从子进程标准输出读取时挂起

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM