我正以这种方式使用两个程序:
$ c_program | python_program.py
c_program使用printf()
打印内容并使用sys.stdin.readline()
读取python_program.py
我想立即打印python_program.py进程c_program的输出,以便它可以打印自己的当前输出。不幸的是,python_program.py仅在c_program结束后获取其输入。
我该如何解决这个问题?
答案 0 :(得分:17)
只需将stdout设置为在C程序开始时进行行缓冲(在执行任何输出之前),如下所示:
#include <stdio.h>
setvbuf(stdout, NULL, _IOLBF, 0);
或
#include <stdio.h>
setlinebuf(stdout);
任何一个都可以在Linux上运行,但setvbuf
是C标准的一部分,因此它可以在更多系统上运行。
默认情况下,stdout将为管道或文件进行块缓冲,或者为终端缓冲行。由于在这种情况下stdout是管道,因此默认将是块缓冲。如果它是块缓冲的,那么当缓冲区已满或者调用fflush(stdout)
时将刷新缓冲区。如果它是行缓冲的,那么它将在每行之后自动刷新。
答案 1 :(得分:8)
你需要的是你的C程序在每一行之后调用fflush(stdout)。例如,使用GNU grep工具,您可以调用选项'--line-buffered',这会导致此行为。请参阅 fflush 。
答案 2 :(得分:7)
答案 3 :(得分:1)
所有Unix shell(我所知道的)都是通过pty以外的东西实现shell管道
(通常,他们使用Unix管道! - );因此,cpp_program
中的C / C ++运行时库将知道它的输出不是终端,因此它将缓冲输出(一次以几KB的块为单位)。除非你编写自己的shell(或semiquasimaybeshelloid)通过pyt实现管道,我相信没有办法用管道符号来做你需要的。
有问题的“shelloid”可能是用Python(或C,或Tcl,或......)编写的,使用标准库的pty
模块或基于它的更高级抽象。作为pexpect,并且通过“基于pty的管道”连接的两个程序是用C ++和Python编写的,这一点非常无关紧要。关键的想法是欺骗管道左边的程序,让它相信它的stdout是一个终端(这就是为什么pty必须在技巧的根源)来欺骗它的运行时库到NOT缓冲输出。一旦你编写了这样的shelloid,你就会用一些语法来调用它,例如:
$ shelloid'cpp_program | python_program.py'
当然,通过编写python_program
知道必须将cpp_program
作为子进程生成并提示它相信其stdout是终端,这将更容易提供“点解决方案” (例如,python_program
将直接使用pexpect
,例如)。但是,如果您有数百万这样的情况,您希望打败由系统提供的C运行时库执行的正常缓冲,或者您希望重用现有过滤器等的许多情况,那么写shelloid
实际上可能是优选的。
答案 4 :(得分:1)
您可能想在cpp程序中尝试flush
stdout流。
答案 5 :(得分:-1)
将您的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"