bash 即时获取另一个程序的输出作为输入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1408678/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting another program's output as input on the fly
提问by Andrea Ambu
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()
c_program 使用打印printf()内容,python_program.py 使用读取内容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.
我想让 python_program.py 在打印时立即处理 c_program 的输出,以便它可以打印自己的当前输出。不幸的是,python_program.py 仅在 c_program 结束后才获取其输入。
How can I solve this?
我该如何解决这个问题?
回答by mark4o
Just set stdout to be line buffered at the beginning of your C program (before performing any output), like this:
只需在 C 程序的开头(在执行任何输出之前)将 stdout 设置为行缓冲,如下所示:
#include <stdio.h>
setvbuf(stdout, NULL, _IOLBF, 0);
or
或者
#include <stdio.h>
setlinebuf(stdout);
Either one will work on Linux, but setvbufis part of the C standard so it will work on more systems.
任何一个都可以在 Linux 上运行,但它setvbuf是 C 标准的一部分,因此它可以在更多系统上运行。
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.
默认情况下,标准输出将为管道或文件进行块缓冲,或为终端缓冲行。由于在这种情况下 stdout 是一个管道,因此默认值将被块缓冲。如果它是块缓冲的,那么缓冲区将在它已满时或在您调用fflush(stdout). 如果它是行缓冲的,那么它将在每行之后自动刷新。
回答by brianegge
回答by nicerobot
回答by Alex Martelli
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_programwill 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.
所有 Unix shell(我知道的)都通过 pty 以外的其他东西实现 shell 管道(通常,它们使用 Unix 管道!-);因此,C/C++ 运行时库cpp_program会知道它的输出不是终端,因此它会缓冲输出(一次几个 KB 的块)。除非您编写自己的 shell(或 semiquasimaybeshelloid)来通过 pyt 实现管道,否则我相信没有办法使用管道符号来完成您需要的操作。
The "shelloid" thing in question might be written in Python (or in C, or Tcl, or...), using the ptymodule 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”可能是用 Python(或 C、Tcl 或...)编写的,使用pty标准库的模块或基于它的更高级别的抽象,例如pexpect,以及要通过“基于 pty 的管道”连接的两个程序是用 C++ 编写的,而 Python 则无关紧要。关键思想是诱使管道左侧的程序相信其 stdout 是一个终端(这就是为什么 pty 必须位于该技巧的根源)以欺骗其运行时库使其不缓冲输出。一旦你编写了这样一个 shelloid,你就可以使用一些语法来调用它,例如:
$ shelloid 'cpp_program | python_program.py'
$ shelloid 'cpp_program | python_program.py'
Of course it would be easier to provide a "point solution" by writing python_programin the knowledge that it must spawn cpp_programas a sub-process AND trick it into believing its stdout is a terminal (i.e., python_programwould then directly use pexpect, 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, writing shelloidmight actually be preferable.
当然,通过写入python_program它必须cpp_program作为子进程产生并欺骗它相信它的标准输出是一个终端(即,python_program然后将直接使用pexpect,例如)的知识来提供“点解决方案”会更容易。但是,如果您有一百万个这样的情况,您想破坏系统提供的 C 运行时库执行的正常缓冲,或者您想重用现有过滤器等的许多情况,那么编写shelloid实际上可能更可取。
回答by Fritz H
You may want to try flushing the stdout stream in the cpp program.
您可能想尝试flush在 cpp 程序中输入 stdout 流。
回答by Abu Aqil
ok this maybe sound stupid but it might work:
好的,这可能听起来很愚蠢,但它可能有效:
output your pgm to a file
将您的 pgm 输出到文件
$ c_program >> ./out.log
develop a python program that read from tail command
开发一个从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"

