Python子进程实时标准输出和标准输入问题

3
我正在尝试设计一个Python脚本来控制一个用C编写的命令行模拟器程序,包括解析输出到屏幕上的值,并给出输入命令。
目前我已经能够捕获模拟器的初始启动输出,但在最后卡住了。
基本上我是这样设置的:我设置了子进程: proc = Popen('./sim1',stdin=PIPE,stdout=PIPE) 然后我有一个循环来处理输出并将其显示到屏幕上(这是为了测试目的,稍后我将从文本输出中取特定的值)。
for line in iter(proce.stdout.readline,''):
    print(line.rstrip())

即使我在printf语句下方添加了fflush(stdout)语句(建议参考此处:catching stdout in realtime from subprocess),所有文本都打印完成后,程序仍然挂起。
我已经添加了一个异常处理程序,在检测到最后一行中的关键字时会中断循环,但这不是我想要的非常优雅的解决方案。
在此循环之后,我有一些代码用于向模拟器输入命令,我可以告诉您它们有效,因为如果我删除用于读取模拟器输出的代码,则发送的退出命令确实会退出模拟器。
似乎我看到的大多数示例都是人们启动子进程、捕获输出,并在进程退出后显示它。我需要捕获输出、显示输出,然后给出新的命令,显示下一个输出,而不退出子进程。
这里是否存在一些根本性的问题导致我的stdout出现问题?

如果我理解正确,你正在错误的方式进行。请查看https://dev59.com/4W865IYBdhLWcg3wi_I2。 - Antonis Christofides
1个回答

2
这是我拥有的代码,它能正常运行。在你的情况下,你可以将logger.info调用替换为print。
import subprocess as sp

def run_long_running_cmd(args, responders=None):
    process = sp.Popen(args, stdout=sp.PIPE, stderr=sp.STDOUT)
    with process.stdout:
        while True:
            output = process.stdout.readline()
            exit_status = process.poll()
            if responders is not None:
                for responder in responders:
                    response = responder(output)
                    if response is not None:
                        process.stdin.write(response)
            if output:
                logger.info('\t' + output.rstrip())
            elif exit_status is not None:
                break

    logger.info('Finished running subprocess.')
    return exit_status

这样做仍然会给我带来同样的问题,因为我需要代码在不退出子进程的情况下移动到 while True: 代码块之外。我想要使用 stdin 给出多个输入命令,并读取每个命令之间发生的输出。 - how2s101
听起来你可能需要在这个循环中触发一个事件,并使用一个委托订阅该事件,以响应特定的标准输出。 - tvt173
这是我现在正在走的一条路,我已经向模拟器添加了一个转义代码,表示当前提示的结束。它有点能用,但由于模拟器的设置方式,完整实现会非常冗长。 - how2s101
以上的代码怎么样?(免责声明:我还没有测试新代码) - tvt173
我最终采取了不同的方向,使用模拟器将数据写入格式化文件,并从中读取,但我会尽快尝试您的更新。 - how2s101

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接