代码之家  ›  专栏  ›  技术社区  ›  Tom

如何在运行shell时禁用标准输出缓冲区

  •  0
  • Tom  · 技术社区  · 5 年前

    我正在使用Python调用Shell脚本

    def run_command(cmd):
        print "Start to run: " + cmd
        run = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        while True:
            line = run.stdout.readline().decode()[:-1]
            if line == '' and run.poll() is not None:
                break
            print line # print the log from shell
        recode = run.returncode
        if recode != 0:
            raise Exception("Error occurs!")
    
        print "End to run: " + cmd
    

    然后我就跑

    run_command("sh /home/tome/a.sh")
    

    我注意到a.sh的控制台输出不是实时的,看起来有一个stdout缓冲区,当stdout缓冲区满时,输出被打印出来。

    我会问如何在脚本a.sh中禁用shell标准输出缓冲区

    谢谢

    0 回复  |  直到 5 年前
        1
  •  3
  •   ShadowRanger    5 年前

    所讨论的缓冲在很大程度上是脚本方面的问题,而不是Python方面的问题;虽然Python会缓冲读取,但它不会阻塞,除非缓冲区被清空,并且没有可读取的内容。

    所以,实际上,需要在脚本本身中禁用缓冲。添加 stdbuf -oL (或 -o0 对于完全无缓冲,但行缓冲应该覆盖您,因为您也可以逐行读取),在某些情况下(程序不在内部调整自己的缓冲),命令应该有帮助。

    如果您只是通过查看Python的输出才看到这种行为,请注意Python本身也可以缓冲输出。你可以通过传递来禁用它 -u 运行Python或设置环境变量时 PYTHONUNBUFFERED=1 在运行它之前,或者在脚本中,可以手动调用 sys.stdout.flush() 在任何写入(直接或隐式)之后 print )去斯特杜特。关于现代Python, 打印 用一个论点来迫使 flush 在打印之后,但是因为您使用的是Python 2。x、 这不是一个选择。