C语言 尝试捕获自由运行输出时,PIPE的python子进程输出问题

zpgglvta  于 2023-01-20  发布在  Python
关注(0)|答案(1)|浏览(170)

输入C程序test. c

#include <stdio.h>

int main(void)
{
    while(1)
    {
        printf("Hello World!\n");
        sleep(1);
    }
    return 0;
}

使用gcc gcc -g -o test test.c编译
运行程序,看看它给出的输出

./test 
Hello World!
Hello World!
Hello World!
^C

使用子进程运行程序以捕获输出

import subprocess
import shlex

cmd = "./test"
def run_command(command):
    cmds = shlex.split(cmd)
    print(cmds)
    proc = subprocess.Popen(cmds, stdout=subprocess.PIPE)
    try:
        outs, errs = proc.communicate(timeout=15)
    except subprocess.TimeoutExpired:
        proc.kill()
        outs, errs = proc.communicate()
    print(outs)
    
run_command(cmd)

输出为空

python3 test.py 
['./test']
b''

cmd = "./test"替换为cmd = "gdb -x load ./test",其中load是带有run命令的文件
输出只是gdb信息,而不是应用程序输出

python3 test.py 
['gdb', '-x', 'load', './test']
b'GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1\nCopyright (C) 2022 Free Software Foundation, Inc.\nLicense GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\nThis is free software: you are free to change and redistribute it.\nThere is NO WARRANTY, to the extent permitted by law.\nType "show copying" and "show warranty" for details.\nThis GDB was configured as "x86_64-linux-gnu".\nType "show configuration" for configuration details.\nFor bug reporting instructions, please see:\n<https://www.gnu.org/software/gdb/bugs/>.\nFind the GDB manual and other documentation resources online at:\n    <http://www.gnu.org/software/gdb/documentation/>.\n\nFor help, type "help".\nType "apropos word" to search for commands related to "word"...\nReading symbols from ./test...\n[Thread debugging using libthread_db enabled]\nUsing host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".\n'
j2datikz

j2datikz1#

您正在查看缓冲问题。当C程序的标准输出是交互设备时,默认情况下,它的输出是行缓冲的。否则,包括标准输出是管道时,它的输出是块缓冲的。
对于行缓冲输出,每个“Hello World!\n”都会因为末尾的换行符而被立即发送到流中;对于块缓冲输出,所有内容都保存在程序内部的缓冲区中,直到缓冲区填满,然后一次发送所有内容。
当通过Python脚本运行时,C程序只向其块缓冲的标准输出写入了大约15行(195字节),不足以填满缓冲区,当通过信号终止进程时,它会立即终止,而不会刷新缓冲区,因此Python脚本不会看到任何输出。
你可以通过在printf()后面添加一个fflush(stdout);来解决这个问题,这可能类似于gdb所做的事情。

相关问题