绕过子输出的缓冲在C或Python POPEN(Bypassing buffering of sub

2019-07-17 17:50发布

我有一个一般性的问题有关popen方法(和所有相关的功能),适用于所有的操作系​​统,当我写一个python脚本或一些C代码,并从控制台运行生成的可执行文件(赢或Linux),我马上就可以看到输出从过程。 但是,如果我运行相同的可执行文件与标准输出重定向到管道分叉过程中,输出缓冲器的地方,通常可以达到4096个字节之前它被写入到父进程可以读取它的管。

下面的python脚本将在1024字节的块中生成输出

import os, sys, time

if __name__ == "__main__":
     dye = '@'*1024
     for i in range (0,8):
        print dye
        time.sleep(1)

下面的python脚本将执行前面的脚本并尽快读取输出,因为它通过字节来管,字节

import os, sys, subprocess, time, thread

if __name__ == "__main__":
    execArgs = ["c:\\python25\\python.exe", "C:\\Scripts\\PythonScratch\\byte_stream.py"]

    p = subprocess.Popen(execArgs, bufsize=0, stdout=subprocess.PIPE)
    while p.returncode == None:
        data = p.stdout.read(1)
        sys.stdout.write(data)
        p.poll()

调整操作系统的路径。 当在这种配置中运行时,输出将不会,出现在1024块,但4096块尽管POPEN命令的缓冲器大小被设置为0(这是默认反正)。 谁能告诉我如何改变这种行为?有没有什么办法可以强制操作系统处理从分叉过程的输出以同样的方式,当它从控制台运行的?,即刚刚经历养活数据无缓冲?

Answer 1:

一般来说,标准C运行库(也就是每一个系统上运行的代表几乎所有程序的,更多或更少的检测;-)标准输出是否是终端与否; 如果不是,它缓冲输出(它可以是一个巨大的胜利的效率相比,无缓冲输出)。

如果你在做这写程序的控制的时候,你可以(作为另一个答案的建议)齐平标准输出连续,或(更优雅如果可行的话),试图迫使标准输出是无缓冲,例如,通过与正在运行的Python的-u命令行旗:

-u     : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)
         see man page for details on internal buffering relating to '-u'

(什么手册页添加为标准输入和二进制模式[S]问题的提及)。

如果你不能或不想触摸所编写的程序, -u或者这只是读取程序等等不太可能帮助(即最重要的缓冲是一个发生在作家的标准输出,而不是一个对读者的标准输入)。 另一种方法是作家欺骗,以为它写到一个终端(即使在事实上它写到另一个程序!),通过pty标准库模块或更高级别的第三方Pexpect的模块(或者,对于Windows,其端口wexpect )。



Answer 2:

那是正确的,并适用于Windows和Linux(和其他可能的系统),与popen()fopen() 。 如果你想被分派前4096个字节,使用输出缓冲区fflush()在C)或sys.stdout.flush() (Python)的。



文章来源: Bypassing buffering of subprocess output with popen in C or Python