加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

使用C或Python中的popen绕过子进程缓冲

发布时间:2020-12-16 05:37:42 所属栏目:百科 来源:网络整理
导读:我有一个关于popen(和所有相关功能)的一般问题,适用于所有操作系统,当我编写一个 python脚本或一些c代码并从控制台(win或linux)运行生成的可执行文件时,我可以立即看到输出从过程中.但是,如果我运行与其stdout重定向到管道中的分叉进程相同的可执行文件,那么
我有一个关于popen(和所有相关功能)的一般问题,适用于所有操作系统,当我编写一个 python脚本或一些c代码并从控制台(win或linux)运行生成的可执行文件时,我可以立即看到输出从过程中.但是,如果我运行与其stdout重定向到管道中的分叉进程相同的可执行文件,那么输出缓冲区将在某个位置通常达到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,subprocess,time,thread

if __name__ == "__main__":
    execArgs = ["c:python25python.exe","C:ScriptsPythonScratchbyte_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()

调整操作系统的路径.当在此配置中运行时,尽管popen命令的缓冲区大小设置为0(这仍是默认值),输出不会以1024的块形式显示,而是块的4096.任何人都可以告诉我如何改变这种行为?有没有什么办法可以强制操作系统以与从控制台运行的方式相同的方式来处理分叉进程的输出,即只需将数据提供给没有缓冲?

解决方法

一般来说,标准的C运行时库(代表每个系统上每个程序运行的程序库,或多或少)都会检测出stdout是否为终端;如果没有,它缓冲输出(与无缓冲输出相比,可以获得巨大的效率赢).

如果你控制着这个写作的程序,你可以(作为另外一个答案),连续刷新stdout,或者(如果可行的话)更加优雅)试图强制stdout是无缓冲的.通过使用-u命令行标志运行Python:

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

(man页面增加的是提到stdin和二进制模式的问题).

如果您不能或不想触摸正在撰写的程序,那么在刚刚阅读的程序上的-u等就不太可能有所帮助(最重要的缓冲是在作者标准上发生的缓冲,而不是一个在读者的标准).另一种选择是嘲弄作者相信它正在写一个终端(尽管实际上是写给另一个程序!),通过pty标准库模块或更高级别的第三方pexpect模块(或者,对于Windows,它的wexpect港).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读