在没有flush()和新行的子进程输出上进行非阻塞读取

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在没有flush()和新行的子进程输出上进行非阻塞读取相关的知识,希望对你有一定的参考价值。

我有一个我无法修改的程序。这个程序打印数据到stdout没有冲洗它或把 放在里面等待输入等等。

我的问题是,我如何从Python脚本中实时打印stdout并写入他的stdin?我找到了一些方法来写他的stdin而不关闭程序,但问题仍然是打印他的stdout

事实上,线程,Popenfcntl有一些问题要实时打印他的输出,但他们都假设程序在每次打印后刷新stdout并在其输出中包含

要清楚,让我说我有一个程序test.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (void)
{
    char name[100], age[100], location[100];
    fprintf (stdout, "
What is your name : ");
    fgets (name, sizeof (name), stdin);
    name[strcspn (name, "
")] = '';
    fprintf (stdout, "How old are you : ");
    fgets (age, sizeof (age), stdin);
    age[strcspn (age, "
")] = '';
    fprintf (stdout, "Where do you live : ");
    fgets (location, sizeof (location), stdin);
    location[strcspn (location, "
")] = '';
    fprintf (stdout, "
Hello %s, you have %s years old and live in 
             %s

", name, age, location);
    return 0;
}

我怎样才能从Python脚本输出第一个fprintf(),然后将答案写入他的stdin,依此类推,就像我可以简单地启动test.c一样?

目的是控制从脚本发送到此程序的数据,并仍然返回发生的情况。

答案

您可以使用以下程序,该程序严重依赖于标准Python语言的subprocess包:

def run_program(cmd, sinput=''):
    """Run the command line and output (ret, sout, serr)."""
    import subprocess

    proc =  subprocess.Popen(cmd,
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
    sin = proc.stdin
    sout, serr = proc.communicate(sinput.encode("utf-8"))
    ret = proc.wait()

    return (ret, sout, serr)

因此,您刚用C编写的程序将提供以下内容:

cmd = ['myprogram']
sinput = 'myname
6
Whitechapel
'
(ret, sout, serr) = run_program(cmd, sinput)

请注意,您无法避免使用 字符,因为目标程序使用它来知道您发送问题的答案。

以上是关于在没有flush()和新行的子进程输出上进行非阻塞读取的主要内容,如果未能解决你的问题,请参考以下文章

实时打印使用 Python 中的子进程启动的 bash 命令的结果

如何在 dplyr 中每 n 行非随机采样?

阻塞进程函数 wait()和waitpid()

管道被 Perl 中的子进程阻塞

MySQL线程处于Waiting for table flush的分析

MySQL线程处于Waiting for table flush的分析