使用管道将数据从C进程发送到Python进程

3
我正在尝试将数据从一个C程序发送到一个Python程序(两个程序同时运行)。我尝试使用C语言中的popen函数。据我所理解,我在C程序中写入文件描述符的任何内容都可以从Python程序的stdin中读取。然而,Python程序似乎停在了从stdin读取的地方。有什么建议吗?
以下是C程序:
test.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(void) {

    FILE * fp = popen("sudo python display.py", "w");
    if (fp == NULL) {
        printf("popen error\n");
        exit(1);
    }

    int inc = 0;
    char buf[10];

    while(1) {
        sprintf(buf, "%d", inc);
        fputs(buf, fp);
        inc++;
        sleep(1);
    }


    return (0);
}

这里是一个Python程序,它应该读取"inc"的值并输出它。

display.py

import sys

value = 0

while(True):
    value = sys.stdin.read()
    print value

该程序似乎在value = sys.stdin.read()处卡住了。我已经尝试使用readline()和readlines(),但结果相同。
2个回答

4

readline() 只有在您从 C 程序中输出了 时才会起作用。

由于您从未打印出换行符,readline 将永远等待。

read() 没有参数时将等到 C 程序退出(或关闭 stdout)。同样,这绝不会发生在您的程序中。


但是在C端没有任何fflush,每秒只写入几个字节,OP需要等待很长时间才能发生一些事情。我猜Python进程实际上从未得到一个单独的字节(因为OP可能需要等待几百秒才能在原始代码上发生这种情况)。 - Basile Starynkevitch

3
你最好使用fprint(3),而不是混用不安全的sprintf(建议使用snprintf(3))和fputs。你真正想要输出整行(因为文本协议非常方便调试)。在Python端使用readline
最后,通过popen(3)获取的FILE*甚至不能保证是行缓冲的(但可能具有更大的缓冲区,例如4K字节或更多)。您可以使用setvbuf(3)设置其缓冲区,但您确实应该使用fflush(3)显式地刷新FILE*缓冲区。如果不这样做,输出可能会在缓冲区中停留很长时间(而没有任何实际的write(2)stdio函数执行,如fprintffputs),因此pipe(7)保持为空。 (所以即使在C端也会遇到问题)

程序似乎在 value = sys.stdin.read() 处卡住了。

我猜测你的 C 代码实际上没有写入任何字节(你可以使用 strace(1) 进行检查),因为你的 fputs 仍然停留在缓冲区中。你可能需要等待很长时间(也许是1000秒,以填充几千字节的缓冲区)才能在管道上实际写入一些东西,因为你忘记了 fflush。

一个 popen 的文件应该被 pclose 关闭。

所以你应该用下面这个(正确的)代码替换你的 while 循环:

while(1) {
    fprintf(fp, "%d\n", inc);
    inc++;
    fflush(fp);
    sleep(1);
}

你的循环应该以某种方式退出。也许你可以捕获一些信号(7) -可能是SIGTERM-(但一定要阅读信号安全(7))。确保使用pclose(以避免僵尸进程)。

(我假设你正在Linux或其他POSIX系统上)


1
谢谢!那个解决了我的问题。 - zainosaurus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接