为什么子进程的标准输出(重定向到无缓冲文件)会被缓冲?
来自 http://docs.python.org/library/functions.html#open
可选的 bufsize 参数指定了文件的缓冲区大小:0 表示不使用缓冲,1 表示按行缓冲,其他正数值则表示使用大约这个大小的缓冲区。负数的 bufsize 表示使用系统默认的设置,通常对于终端设备是按行缓冲,而对于其他文件则是完全缓冲。如果不指定这个参数,就会使用系统默认值。
我在下面传入了 0 作为 bufsize,但在运行 main_process 时,如果不使用 flush(),文件里没有任何输出。
这是为什么呢?
# --------------------------------- 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()
2 个回答
8
在使用Python的时候,可以加上一个“-u”这个标志,比如:
if __name__ == '__main__':
p = subprocess.Popen(
['python', '-u', 'sub_process.py'],
stdout=open('std-output', 'w'))
time.sleep(3)
p.terminate()
5
扩展一下Magnus Skog的解决方案(顺便说一下,赞一个 :)):
基本上发生的事情是,当子进程要创建一个新进程时,它会把标准输出(stdout)的设置复制到新进程的标准输出上(文件编号 = 1),这个过程是通过os.dup2来实现的(可以查看subprocess.Popen._execute_child)。这样做会保持无缓冲状态(dup2的作用就是这样),到这里一切都很好。但是,当Python在子进程中启动时,如果没有看到-u这个标志,Python默认会把标准输出的缓冲设置为行缓冲(可以查看main python function),这就会覆盖你之前设置的缓冲标志。
希望这能更好地解释你所看到的行为。