当尝试读取 C 程序的输出时,即“2000 ,”来自使用 subprocess 的 Python 脚本,该脚本挂在“for line in iter(process.stdout.readline, '')”行。尽管 C 程序不断打印“2000”并且从未达到结束状态,但还是会出现这种情况。
问题源于块缓冲问题。默认情况下,通过管道运行的 C 程序中的 stdout(例如,当使用 subprocess.Popen 时)是块缓冲的。这意味着在缓冲区已满或显式刷新之前,数据不会刷新到管道。
选项 1:直接修改 C 程序
要解决此问题,您可以强制 stdout 在 C 程序中进行行缓冲:
#include <stdio.h> int main() { setvbuf(stdout, (char *) NULL, _IOLBF, 0); // Make line buffered stdout while (1) { printf("2000\n"); sleep(1); } return 0; }
选项 2:使用 stdbuf 实用程序
或者,您可以使用 stdbuf 实用程序来更改在不修改 C 程序源的情况下缓冲类型:
from subprocess import Popen, PIPE process = Popen(["stdbuf", "-oL", "./main"], stdout=PIPE, bufsize=1) for line in iter(process.stdout.readline, b''): print(line) process.communicate()
选项 3:使用伪 TTY
另一种方法涉及使用伪 TTY 来欺骗 C 程序认为它正在交互运行:
import os import pty import sys from select import select from subprocess import Popen, STDOUT master_fd, slave_fd = pty.openpty() process = Popen("./main", stdin=slave_fd, stdout=slave_fd, stderr=STDOUT, bufsize=0, close_fds=True) timeout = .1 with os.fdopen(master_fd, 'r+b', 0) as master: input_fds = [master, sys.stdin] while True: fds = select(input_fds, [], [], timeout)[0] # Handle subprocess output and user input here
选项 4:使用 pexpect
Pexpect 提供了一个更高级别的接口,可以简化伪 TTY 处理:
import pexpect child = pexpect.spawn("./.main") for line in child: print(line) child.close()
以上是为什么我的 Python `subprocess.readline` 在读取连续编写的 C 程序时会挂起?的详细内容。更多信息请关注PHP中文网其他相关文章!