Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 获得另一个程序';将输出作为动态输入_Python_C_Linux_Bash_Stdio - Fatal编程技术网

Python 获得另一个程序';将输出作为动态输入

Python 获得另一个程序';将输出作为动态输入,python,c,linux,bash,stdio,Python,C,Linux,Bash,Stdio,我有两个这样使用的程序: $ c_program | python_program.py c_程序使用printf()打印内容,python_program.py使用sys.stdin.readline() 我想让python_program.py在打印时立即处理c_程序的输出,这样它就可以打印自己的当前输出。不幸的是,python_program.py只有在c_程序结束后才能获得输入 我怎样才能解决这个问题 据我所知,所有unixshell都通过pty以外的东西实现shell管道 (通常,他

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

$ c_program | python_program.py
c_程序使用
printf()
打印内容,python_program.py使用
sys.stdin.readline()

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

我怎样才能解决这个问题

据我所知,所有unixshell都通过pty以外的东西实现shell管道 (通常,他们使用Unix管道!);因此,
cpp_程序
中的C/C++运行时库将知道其输出不是终端,因此它将缓冲输出(一次几KB的块)。除非您编写自己的shell(或半准mybeshelloid)通过pyt实现管道,否则我相信使用管道表示法无法实现您所需的功能

< P> >“SelLID”的问题可能是用Python(或C或TCL,或…)编写的,使用标准库的“代码”> pTy < /C>模块或基于它的高级抽象,以及两个程序通过“基于PtY的流水线”连接的事实,用C++编写,Python非常不相关。关键的想法是欺骗管道左侧的程序,使其相信其stdout是一个终端(这就是为什么pty必须位于欺骗的根源),从而欺骗其运行时库,使其不缓冲输出。一旦编写了这样一个shelloid,您就可以使用一些语法来调用它,例如:

$shelloid'cpp_program | python_program.py'


当然,通过编写
python_程序
来提供“点解决方案”会更容易,因为它必须生成
cpp_程序
作为子进程,并诱使它相信其stdout是终端(例如,
python_程序
将直接使用
pexpect
)。但是如果您有一百万种这样的情况,您想破坏由系统提供的C运行时库执行的正常缓冲,或者在许多情况下您想重用现有的过滤器,等等,编写shelloid实际上可能更可取。

您可能希望尝试在cpp程序中刷新stdout流。

您需要的是让您的C程序在每行之后调用fflush(stdout)。例如,使用GNU grep工具,您可以调用选项“-line buffered”,这会导致这种行为。请参见

好的,这可能听起来很愚蠢,但可能有用:

将您的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"

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

#include <stdio.h>
setvbuf(stdout, NULL, _IOLBF, 0);
#包括
setvbuf(标准输出,NULL,_IOLBF,0);

#包括
setlinebuf(标准输出);
其中任何一个都可以在Linux上运行,但是
setvbuf
是C标准的一部分,因此它可以在更多的系统上运行


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

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


有一个名为的示例脚本,可以实现这一点。

您所说的输出量是多少?这涉及到缓冲区,所以4K以下的任何东西都将是单一的。没有办法决定何时刷新缓冲区吗?遗憾的是,这不起作用。问题主要在于C程序的输出是缓冲的,而Python程序中没有任何方法可以影响这一点。您必须修复C程序,使其输出即使进入管道也不会被缓冲。非常感谢。这帮助我在srcds_linux中编写了一个重启程序。我只是把它作为插件放到游戏服务器中,瞧。。stdout以行的形式出现,而不是以4k块的形式出现。
#include <stdio.h>
setlinebuf(stdout);