为什么我的 Python `subprocess.readline` 在读取连续编写的 C 程序时会挂起?

Linda Hamilton
发布: 2024-11-19 16:09:03
原创
536 人浏览过

Why Does My Python `subprocess.readline` Hang When Reading from a Continuously Writing C Program?

Python 子进程 readline 挂在“for line in iter”

问题

当尝试读取 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中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板