Python脚本将终端和重定向之间的输出与文件区分开来

时间:2015-01-15 15:58:39

标签: python output stdout

我正在编写一个带有各种subprocess.call的大型python脚本来执行系统中可用的命令,我遇到了一个问题,因为如果打印到终端或者重定向到文件,输出会有所不同。

为了重现问题,这只是脚本的一小部分:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from subprocess import call

print "Hello at first"
call(["rsync", "-aHvz", "root@server1:/tmp/a", '.'])
print "Hello at the end"

从终端执行它以正确的顺序返回,打印+ rsync + print:

$ python keepconf.py
Hello at the first
receiving incremental file list

sent 12 bytes  received 123 bytes  270.00 bytes/sec
total size is 55858143  speedup is 413764.02
Hello at the end

执行相同操作,但将输出重定向到文件:

$ python keepconf.py  > /tmp/output
$ cat /tmp/output
receiving incremental file list

sent 12 bytes  received 123 bytes  270.00 bytes/sec
total size is 55858143  speedup is 413764.02
Hello at the first
Hello at the end

现在订单是rsync + print + print。为什么会出现这种情况?

1 个答案:

答案 0 :(得分:4)

终端的输出(或者更准确地说,是tty)通常在Python中以行缓冲模式打开。当您使用管道时,Python将使用固定大小的不同缓冲区。

这意味着当您使用换行符写入文本时,缓冲区会在打印到终端时自动刷新,但是对于管道,只有在缓冲区已满或强制刷新时才会刷新(例如当Python脚本退出时。)

换句话说,当写入终端时,在运行rsync命令之前,第一个打印行被刷新到终端。当重定向到管道时,文本保存在缓冲区中,运行rsync命令输出(在刷新时写入管道,至少一次在结束时但可能更频繁),之后你写一些更多的缓冲区,当Python存在时,缓冲区被刷新到管道。

您可以手动强制冲洗:

import sys

# ....
print "Hello at first"
sys.stdout.flush()
call(["rsync", "-aHvz", "root@server1:/tmp/a", '.'])
print "Hello at the end"
sys.stdout.flush()