使用Python强制另一个程序的标准输出无缓冲

时间:2009-10-09 14:15:36

标签: python linux pipe stdout

python脚本控制Linux上的外部应用程序,通过管道将输入传递到外部应用程序stdin,并通过外部应用程序stdout中的管道读取输出。

问题是对管道的写入是按块而不是按行缓冲的,因此在控制脚本通过外部应用程序中的printf接收数据输出之前会发生延迟。

无法更改外部应用程序以添加显式fflush(0)调用。

如何将python标准库的pty模块与subprocess模块一起使用来实现这一目标?

7 个答案:

答案 0 :(得分:6)

您可以使用PTY来解决此问题:

  • 创建一个pty主/从对;
  • 将子进程的stdin,stdout和stderr连接到pty slave设备;
  • 读取和写入父母的pty主人。

答案 1 :(得分:5)

这样做是可能的,但我能想到的唯一解决方案是相当复杂,不可移植,并且可能充满了有问题的细节。您可以使用LD_PRELOAD使外部应用程序加载动态库,该库包含一个调用setvbuf到unbuffer stdout的构造函数。您可能还希望在库中包装setvbuf以防止应用程序显式缓冲其自己的stdout。并且你想要包装fwrite和printf,以便它们在每次调用时刷新。编写要预加载的.so会将你带到python之外。

答案 2 :(得分:3)

我不认为这是可能的。如果源应用程序没有刷新其传出缓冲区,则在缓冲区溢出并强制刷新之前,数据将不会到达该进程之外。

注意一个成熟的命令如file如何有一个选项(-n),它会导致它显式刷新它的输出。在从管道读取输入文件名的模式下使用文件时,这是必需的,并打印检测到的类型。由于在此模式下,文件程序在完成后不会退出,否则输出将不会出现。

在较低级别考虑这一点:输出缓冲只是意味着对缓冲流执行write()会将数据复制到内存缓冲区中,直到缓冲区填满或(通常)直到找到换行符为止。然后,缓冲区直到溢出或换行的部分被写入write() n到底层系统级文件描述符(可以是文件,管道,套接字......)。

我不明白你是如何说服程序从外面冲洗它的缓冲区。

答案 3 :(得分:2)

值得注意的是,有些程序只会在认为它不是“真实用户”(即tty)时才会缓冲输出。当他们检测到他们的输出被另一个程序读取时,它们会缓冲。

模拟tty是Expect在自动化其他过程中所做的事情之一。

有一个pure Python implementation of Expect,但我不知道它如何处理tty仿真。

答案 4 :(得分:2)

这个问题的答案可能有所帮助:

Python Run a daemon sub-process & read stdout

似乎正在解决同样的问题。

答案 5 :(得分:1)

这个问题有点陈旧,但我认为现在可以通过使用子进程使用您要执行的命令调用stdbuf来解决问题。

答案 6 :(得分:-1)

尝试使用-u参数运行Python解释器:

python -u myscript.py

这迫使Python使用无缓冲的stdin / stdout,这可能对你有帮助。