我有两个程序,我用这种方式:
$ c_program | python_program.py
c_program使用printf()
和python_program.py使用sys.stdin.readline()
读取数据,
我想使python_program.py进程c_program的输出,因为它立即打印,以便它可以打印自己的当前输出。 不幸的是python_program.py只有在c_program结束之后才能获得input。
我该如何解决这个问题?
只需将stdout设置为在C程序的开头进行行缓冲(在执行任何输出之前),如下所示:
#include <stdio.h> setvbuf(stdout, NULL, _IOLBF, 0);
要么
#include <stdio.h> setlinebuf(stdout);
任何一个都可以在Linux上工作,但是setvbuf
是C标准的一部分,所以它可以在更多的系统上工作。
默认情况下,标准输出将被阻塞缓冲管道或文件,或线路缓冲的终端。 由于stdout在这种情况下是一个管道,所以默认情况下会被阻塞。 如果是块缓冲,那么当缓冲区满了或者调用fflush(stdout)
时,缓冲区将被刷新。 如果是行缓冲,那么每行之后会自动刷新。
你需要的是你的C程序在每行之后调用fflush(stdout)。 例如,使用GNU grep工具,您可以调用选项“–line-buffered”,这会导致此行为。 见fflush 。
如果你可以修改你的C程序,你已经收到你的答案,但我想我会包括那些不能/不会修改代码的解决方案。
期望有一个名为unbuffer的示例脚本,可以做到这一点。
所有的Unix shell(我知道)都是通过别的东西来实现shell管道的(比如通常使用Unix管道)。 因此, cpp_program
的C / C ++运行时库将知道它的输出不是一个终端,因此它将缓冲输出(一次以几KB为单位)。 除非你编写自己的shell(或semiquasimaybeshelloid)通过pyt来实现管道,否则我相信没有办法用流水线符号来做你所需要的。
所讨论的“shelloid”可能是用Python(或者C,或者Tcl,或者…)编写的,使用标准库的pty
模块或者基于它的更高级的抽象,例如pexpect ,通过“基于pty的管道”连接的两个程序是用C ++编写的,而Python是非常不相关的。 关键的想法是欺骗程序到管道的左侧,相信它的标准输出是一个终端(这就是为什么一个pty必须在这个技巧的根源)来愚弄它的运行时库到NOT缓冲输出。 一旦你写了这样一个shelloid,你可以用下面的语法来调用它:
$ shelloid'cpp_program | python_program.py”
当然,通过编写python_program
知道它必须产生cpp_program
作为一个子进程,并欺骗它相信它的stdout是一个终端(也就是说, python_program
会直接使用pexpect
,for例)。 但是,如果你有一百万个这样的情况,你想打破由系统提供的C运行时库执行的正常缓冲,或者你想重用现有过滤器的许多情况下,编写shelloid
可能实际上是更好的。
您可能想要尝试在cpp程序中flush
stdout流。
确定这可能听起来很愚蠢,但它可能工作:
输出你的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"