2011-05-07 28 views
9

http://docs.python.org/library/functions.html#open为什么要缓冲子进程的标准输出(重定向到无缓冲文件)?

可选BUFSIZE参数 指定文件的所需的缓冲区 大小: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() 
+0

+1,我花了大约30分钟试图找出为什么'sys.stdout' - >'subprocess.PIPE'几天前没有工作。 'flush()'是答案,但我们为什么需要它? – 2011-05-07 17:21:40

回答

5

扩展马格努斯斯科格溶液(+1顺便说一下:)):

嗯,基本上什么情况是,当子将分叉一个新的进程,它将使用os.dup2(看看subprocess.Popen._execute_child)复制stdout参数到新的子进程标准输出(fileno = 1),这将保持未缓冲状态(如dup2所做的那样),直到现在一切都很好,但是当python默认启动时(在子进程中),如果python没有看到-u标志会将stdout的缓冲区设置为行缓冲区(请参阅main python function。),它将覆盖您之前设置的缓冲标志。

希望这解释更多的你看到的行为。

+0

+1 back :)感谢您澄清这一点。 – ralphtheninja 2011-05-08 10:13:13

6

使用Python -u标志,如:

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

这工作,谢谢。虽然,我仍然想知道为什么它需要? – 2011-05-07 17:15:44

+0

我的猜测是,如果你用file.write()直接写入文件,它将被缓冲,但事实上你正在间接地写它,因为python会在你的文件发送数据之前缓冲你的打印命令,因此你需要-u标志来告诉python不缓冲打印命令。 – ralphtheninja 2011-05-07 17:25:16

+0

'sys.stdout.write('from redirect.py'打印)'给出了与打印相同的结果 - 没有任何东西被写入文件 – 2011-05-07 17:45:01