Python的C子进程:sub.stdin.write IOError Broken Pipe

时间:2013-12-20 11:38:22

标签: python c subprocess broken-pipe

在向C子进程非常快速地写入大量数据时,我遇到了一个Broken Pipe错误。

所以我从python脚本运行一个c子进程:

process = subprocess.Popen("./gpiopwm", stdin=subprocess.PIPE)
while True:
    process.stdin.write("m2000\n")
    print "bytes written"

gpiopwm.c主循环的确定:

printf("1\n");
while (1) {
    fgets(input,7,stdin);  // Takes input from python script
    printf("2\n");

    numbers = input+1;      // stores all but first char of input 
    char first = input[0];  // stores first char of input

    if (first=='m') {
        printf("3\n");
        printf("%s\n",numbers);
    }
}

但是,此输出如下:

1
bytes written
Traceback (most recent call last):
     File "serial-receive-to-pwm.py", line 20, in <module>
     process.stdin.write("m2000\n")
IOError: [Errno 32] Broken pipe

C程序显然在fgets行中断,因为永远不会打印2。 我做错了什么?我怎么能避免这个?

编辑: 我已经更新了fgets行,因此它不包含dereference参数,但仍然会收到管道错误。

编辑: input初始化为char *input="m2000";

1 个答案:

答案 0 :(得分:2)

如果您尝试从控制台运行C程序,您将看到它崩溃。如果你在调试器中运行,你会发现它在这一行:

fgets(*input,7,stdin);

似乎input是一个字符数组,当你用*input取消引用时,你传递的不是指针而是一个char值。这会导致未定义的行为和崩溃。

如果不是错误,该行应该给你,然后是来自编译器的非常大的警告消息。不要忽视警告信息,它们通常表明你做错了什么并且可能很危险。


一般提示:在开发应该从其他程序调用的程序时,就像在此处一样, test 程序首先确保程序正常运行。如果它不起作用,请先修复它。

最后提示:请记住,fgets 包含目标字符串中的换行符。您可能需要检查它并将其删除(如果有的话)。


使用上一次编辑,显示input的声明我们知道真正的问题:您正在尝试修改常量数据,并且您还希望超出界限数据也是如此。

当您使input指向文字字符串时,您必须记住所有文字字符串都是只读,您无法修改文字字符串。尝试这样做是未定义的行为。更糟糕的是,你的字符串只有六个字符长,但你试着写七个字符。

首先更改input的声明和初始化:

char input[16] = "m2000\n";

这会将它声明为一个数组,位于堆栈上并且可以修改。然后做

while (fgets(input, sizeof(input), stdin) != NULL) { ... }

这完成了两件事:首先使用sizeof(input)作为大小,你可以确定fgets永远不会写出界限。其次,通过在循环条件中使用fgets调用,循环将在Python脚本中断时结束,并且您将永远不会循环读取任何内容,然后处理您从未读过的数据。< / p>