【问题标题】:Why is standard output from subprocess (redirected to unbuffered file) being buffered?为什么子进程的标准输出(重定向到无缓冲文件)被缓冲?
【发布时间】:2011-08-20 19:43:53
【问题描述】:

来自http://docs.python.org/library/functions.html#open

可选的 bufsize 参数 指定文件所需的缓冲区 size:0 表示无缓冲,1 表示行 缓冲,任何其他正值 意味着使用(大约)的缓冲区 那个尺寸。负的 bufsize 意味着 使用系统默认值,即 通常为 tty 设备行缓冲 并为其他文件完全缓冲。如果 省略,使用系统默认值。

我在下面将 0 作为 bufsize 传递,但没有使用 flush(),当我运行 main_process 时,没有输出写入文件。
是什么原因?

# --------------------------------- sub_process.py
import sys
import time

if __name__ == '__main__':
    print 'printed from redirect.py'
    # why is the following flush() needed? 'std-output' is (?) unbuffered...
    sys.stdout.flush() 
    time.sleep(6)


# --------------------------------- main_process.py
import subprocess
import time

if __name__ == '__main__':
    p = subprocess.Popen(
        ['python', 'sub_process.py'],
        stdout=open('std-output', 'w', 0))
    time.sleep(3)
    p.terminate()

【问题讨论】:

  • +1,我花了大约 30 分钟试图弄清楚为什么 sys.stdout -> subprocess.PIPE 几天前没有工作。 flush() 是答案,但我们为什么需要它???

标签: python subprocess stdout popen buffering


【解决方案1】:

使用带有 -u 标志的 python,例如:

if __name__ == '__main__':
    p = subprocess.Popen(
        ['python', '-u', 'sub_process.py'],
        stdout=open('std-output', 'w'))
    time.sleep(3)
    p.terminate()

【讨论】:

  • 这行得通,谢谢。不过,我仍然想知道为什么需要它?
  • 我的猜测是,如果您使用 file.write() 直接写入文件,它将无缓冲地完成,但实际上您是间接写入它,因为 python 会在发送之前缓冲您的打印命令数据到您的文件,因此您需要 -u 标志来告诉 python 不要缓冲打印命令。
  • sys.stdout.write('printed from redirect.py') 给出与打印相同的结果 - 没有任何内容被写入文件
【解决方案2】:

扩展 Magnus Skog 解决方案(顺便说一下 +1 :)):

基本上发生的事情是,当子进程将派生一个新进程时,它将使用 os.dup2 将 stdout 参数复制到新的子进程 stdout (fileno = 1)(查看subprocess.Popen._execute_child),这将保持无缓冲状态(就像 dup2 所做的那样),到目前为止一切都很好,但是当 python 将默认启动(在子进程中)时,如果 python 没有看到 -u 标志,它会将 stdout 的缓冲区设置为行缓冲区(看看main python function.),它将覆盖您之前设置的缓冲标志。

希望这能更多地解释您所看到的行为。

【讨论】:

    猜你喜欢
    • 2016-10-25
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    • 2013-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多