使用subprocess.call调用C程序时输出顺序异常问题咨询
现象成因
该问题的核心是C标准库(stdio)的默认缓冲策略,具体规则如下:
- 当标准输出(stdout)绑定交互式终端(手动在终端执行C程序)时,默认使用行缓冲:遇到换行符
\n就会立刻把缓冲区内容刷到终端展示。 - 当标准输出(stdout)未绑定交互式终端(被Python subprocess调用、输出重定向到管道/文件)时,默认使用全缓冲:只有缓冲区写满、程序主动调用
fflush(stdout)、或者程序正常退出时,才会把缓冲区的内容统一输出。
你遇到的执行顺序异常完全符合全缓冲的运行逻辑:
- C程序的
printf("Inside C Program!\n")、printf("Enter a Number: ")内容都被暂存到stdout缓冲区,不会立刻打印到终端 - 执行
scanf()时,C标准库只会刷新标准输入(stdin)对应的缓冲区,不会主动刷新stdout缓冲区,因此终端无任何C程序的提示信息,直接等待用户输入 - 输入完成后C程序运行结束退出,此时才会一次性把stdout缓冲区的所有内容打印到终端,就出现了先输入、后看到C程序提示的异常表现。
解决方法
方法1:修改C代码主动刷新缓冲
在scanf执行前、或者每条printf之后手动调用fflush(stdout)强制刷出缓冲区内容:
#include <stdio.h> int main(void){ int num; printf("Inside C Program!\n"); fflush(stdout); printf("Enter a Number: "); fflush(stdout); scanf("%d", &num); printf("%d\n", num*num); return 0; }
方法2:Python侧模拟交互式终端调用
使用伪终端模块模拟交互式终端环境,让C程序的stdio默认走行缓冲策略:
import subprocess import pty import os def run_c(): subprocess.call(['gcc', '-o', 'c', 'testC.c']) master, slave = pty.openpty() p = subprocess.Popen('./c.exe', stdin=slave, stdout=slave, stderr=slave, text=True) os.close(slave) while True: try: data = os.read(master, 1024) if not data: break print(data.decode(), end='', flush=True) except OSError: break p.wait() os.close(master) def main(): print("Inside Python Code") run_c() print('Task is done') if __name__ == '__main__': main()
内容的提问来源于stack exchange,提问作者Benny
相关产品推荐
相关产品推荐

