代码之家  ›  专栏  ›  技术社区  ›  Andrea Ambu

动态获取另一个程序的输出作为输入

  •  10
  • Andrea Ambu  · 技术社区  · 15 年前

    我有两个这样使用的程序:

    $ c_program | python_program.py
    

    C_程序使用 printf() 和python_program.py使用 sys.stdin.readline()

    我想让python_program.py在打印时立即处理c_程序的输出,以便它可以打印自己的当前输出。不幸的是,python_program.py只有在c_程序结束后才得到输入。

    我怎么解决这个问题?

    6 回复  |  直到 14 年前
        1
  •  17
  •   mark4o    15 年前

    只需将stdout设置为C程序开始时的行缓冲(在执行任何输出之前),如下所示:

    #include <stdio.h>
    setvbuf(stdout, NULL, _IOLBF, 0);
    

    #include <stdio.h>
    setlinebuf(stdout);
    

    任何一个都可以在Linux上工作,但是 setvbuf 是C标准的一部分,因此它将在更多系统上工作。

    默认情况下,stdout将为管道或文件进行块缓冲,或为终端进行行缓冲。在这种情况下,由于stdout是一个管道,因此默认值将被块缓冲。如果缓冲区是块缓冲的,则当缓冲区已满或调用 fflush(stdout) . 如果它是行缓冲的,那么它将在每行之后自动刷新。

        2
  •  8
  •   brianegge    15 年前

    你需要的是你的C程序在每一行后调用fflush(stdout)。例如,使用gnu grep工具,可以调用选项“--line buffered”,这会导致此行为。见 fflush .

        3
  •  6
  •   Community CDub    8 年前

    如果你可以修改你的C程序,你已经收到你的 answer 但我想我应该为那些不能/不会修改代码的人提供一个解决方案。

    expect 有一个名为 unbuffer 这就行了。

        4
  •  1
  •   Alex Martelli    15 年前

    所有的unix shell(我知道)都是通过一个pty以外的东西来实现shell管道的。 (通常,它们使用Unix管道!),因此,C/C++运行时库 cpp_program 将知道它的输出不是一个终端,因此它将缓冲输出(一次以几KB为单位)。除非您编写自己的shell(或semiquasimaybeshelloid),通过pyt实现管道,否则我相信没有办法使用管道符号来完成您需要的工作。

    所讨论的“shelloid”可以用python(或c、tcl或…)编写,使用 pty 标准库的模块或基于它的更高级别抽象,例如 pexpect 这两个程序通过一个“基于PTY的管道”连接的事实是用C++编写的,Python是非常不相关的。关键的想法是欺骗管道左边的程序相信它的stdout是一个终端(这就是为什么一个pty必须是技巧的根),以欺骗它的运行库不缓冲输出。一旦你写了这样一个shelloid,你可以用如下语法来命名它:

    $shelloid'cpp_程序python_程序.py'

    当然,通过写作来提供“点解决方案”会更容易。 python_program 因为它必须产生 CPP-U程序 作为一个子进程,欺骗它相信它的stdout是一个终端(即, Python程序 然后直接使用 pexpect 例如)。但是,如果您有无数这样的情况,您希望击败由系统提供的C运行时库执行的正常缓冲,或者在许多情况下,您希望重用现有的过滤器,等等,请编写 shelloid 可能更可取。

        5
  •  1
  •   Fritz H    15 年前

    你可能想试试 flush 在cpp程序中使用stdout流。

        6
  •  -1
  •   Abu Aqil    15 年前

    好吧,这听起来可能很愚蠢,但可能会奏效:

    将PGM输出到文件

    $ c_program >> ./out.log
    

    开发一个从tail命令读取的python程序

    import os
    
    tailoutput = os.popen("tail -n 0 -f ./out.log")
    
    try:
        while 1:
            line = tailoutput.readline()
            if len(line) == 0:
                break
    
            #do the rest of your things here
            print line
    
    except KeyboardInterrupt:
            print "Quitting \n"