python脚本控制Linux上的外部应用程序,通过管道将输入传递到外部应用程序stdin,并通过外部应用程序stdout中的管道读取输出。
问题是对管道的写入是按块而不是按行缓冲的,因此在控制脚本通过外部应用程序中的printf接收数据输出之前会发生延迟。
无法更改外部应用程序以添加显式fflush(0)调用。
如何将python标准库的pty模块与subprocess模块一起使用来实现这一目标?
答案 0 :(得分:6)
您可以使用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)
答案 5 :(得分:1)
这个问题有点陈旧,但我认为现在可以通过使用子进程使用您要执行的命令调用stdbuf来解决问题。
答案 6 :(得分:-1)
尝试使用-u参数运行Python解释器:
python -u myscript.py
这迫使Python使用无缓冲的stdin / stdout,这可能对你有帮助。