即时获取另一个程序的输出作为输入
我以这种方式使用两个程序:
$ c_program | python_program.py
c_program 使用 printf()
打印一些内容,而 python_program.py 使用 sys.stdin.readline()
读取
内容就像让 python_program.py 在打印时立即处理 c_program 的输出,以便它可以打印自己的当前输出。不幸的是,python_program.py 仅在 c_program 结束后才获取输入。
我该如何解决这个问题?
I've two programs I'm using in this way:
$ c_program | python_program.py
c_program prints something using printf()
and python_program.py reads using sys.stdin.readline()
I'd like to make the python_program.py process c_program's output as it prints, immediately, so that it can print its own current output. Unfortunately python_program.py gets its input only after c_program ends.
How can I solve this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
只需在 C 程序开头(在执行任何输出之前)将 stdout 设置为行缓冲,如下所示:
或
两者之一都可以在 Linux 上工作,但
setvbuf
是 C 标准的一部分,因此它将在更多系统上工作。默认情况下,stdout 将为管道或文件进行块缓冲,或为终端进行行缓冲。由于本例中 stdout 是管道,因此默认情况下将进行块缓冲。如果它是块缓冲的,那么当缓冲区已满或调用
fflush(stdout)
时,缓冲区将被刷新。如果它是行缓冲的,那么它将在每行之后自动刷新。Just set stdout to be line buffered at the beginning of your C program (before performing any output), like this:
or
Either one will work on Linux, but
setvbuf
is part of the C standard so it will work on more systems.By default stdout will be block buffered for a pipe or file, or line buffered for a terminal. Since stdout is a pipe in this case, the default will be block buffered. If it is block buffered then the buffer will be flushed when it is full, or when you call
fflush(stdout)
. If it is line buffered then it will be flushed automatically after each line.您需要的是让您的 C 程序在每一行之后调用 fflush(stdout) 。例如,使用 GNU grep 工具,您可以调用选项“--line-buffered”,这会导致此行为。请参阅fflush。
What you need is for your C program to call fflush(stdout) after every line. For example, with the GNU grep tool, you can invoke the option '--line-buffered', which causes this behavior. See fflush.
如果您可以修改 C 程序,则您已经收到了 答案,但我想我应该为那些不能/不会修改代码的人提供一个解决方案。
expect 有一个名为 unbuffer 就可以了。
If you can modify your C program, you've already received your answer but i thought i'd include a solution for those that can't/won't modify code.
expect has an example script called unbuffer that will do the trick.
您可能想尝试刷新 cpp 程序中的 stdout 流。
You may want to try
flush
ing the stdout stream in the cpp program.所有 Unix shell(据我所知)都通过 pty 之外的其他方式实现 shell 管道
(通常,他们使用 Unix 管道!-);因此,
cpp_program
中的 C/C++ 运行时库将知道其输出不是终端,因此它将缓冲输出(一次几 KB 的块)。除非您编写自己的 shell(或 semiquasimaybeshelloid)来通过 pyt 实现管道,否则我相信无法使用管道表示法来完成您所需要的操作。所讨论的“shelloid”可能是用 Python(或 C、Tcl 或...)编写的,使用标准库的 pty 模块或基于它的高级抽象,例如作为 pexpect,以及两个程序通过“基于 pty 的管道”连接的事实" 是用 C++ 编写的,而 Python 是相当无关紧要的。关键思想是欺骗管道左侧的程序,使其相信其 stdout 是一个终端(这就是为什么 pty 必须是该技巧的根源),以欺骗其运行时库不缓冲输出。一旦编写了这样的 shelloid,您就可以使用一些语法来调用它,例如:
$ shelloid 'cpp_program | python_program.py'
当然,通过编写
python_program
来提供“点解决方案”会更容易,因为知道它必须生成cpp_program
作为子进程并欺骗它相信它的标准输出是一个终端(例如,python_program
将直接使用pexpect
)。但是,如果您有数百万种这样的情况,您想要击败系统提供的 C 运行时库执行的正常缓冲,或者您想要重用现有过滤器等许多情况,请编写shelloid
实际上可能更可取。All the Unix shells (that I know of) implement shell pipelines via something else than a pty
(typically, they use Unix pipes!-); therefore, the C/C++ runtime library in
cpp_program
will KNOW its output is NOT a terminal, and therefore it WILL buffer the output (in chunks of a few KB at a time). Unless you write your own shell (or semiquasimaybeshelloid) that implements pipelines via pyt's, I believe there is no way to do what you require using pipeline notation.The "shelloid" thing in question might be written in Python (or in C, or Tcl, or...), using the
pty
module of the standard library or higher-level abstraction based on it such as pexpect, and the fact that the two programs to be connected via a "pty-based pipeline" are written in C++ and Python is pretty irrelevant. The key idea is to trick the program to the left of the pipe into believing its stdout is a terminal (that's why a pty must be at the root of the trick) to fool its runtime library into NOT buffering output. Once you have written such a shelloid, you'd call it with some syntax such as:$ shelloid 'cpp_program | python_program.py'
Of course it would be easier to provide a "point solution" by writing
python_program
in the knowledge that it must spawncpp_program
as a sub-process AND trick it into believing its stdout is a terminal (i.e.,python_program
would then directly usepexpect
, for example). But if you have a million of such situations where you want to defeat the normal buffering performed by the system-provided C runtime library, or many cases in which you want to reuse existing filters, etc, writingshelloid
might actually be preferable.好吧,这可能听起来很愚蠢,但它可能有效:
将你的 pgm 输出到文件中,
开发一个从 tail 命令读取的 python 程序
ok this maybe sound stupid but it might work:
output your pgm to a file
develop a python program that read from tail command