如何将脚本输出写入文件和命令行?

7

我有一个长时间运行的Python脚本,从命令行运行。该脚本将进度消息和结果写入标准输出。我想在文件中捕获脚本写入到标准输出的所有内容,但也要在命令行上看到它。或者,我希望输出立即进入文件,这样我就可以使用tail查看进度。我尝试过以下方法:

python MyLongRunngingScript.py | tee log.txt

但是它没有产生任何输出(只有运行脚本才会产生预期的输出)。有人可以提出一个简单的解决方案吗?我正在使用Mac OS X 10.6.4。
编辑:在我的脚本中,我使用print输出。
4个回答

17

你走在正确的道路上,但问题在于Python会对输出进行缓存。

幸运的是,有一种方法可以告诉Python不要对输出进行缓存:

python -u MyLongRunngingScript.py | tee log.txt

3
如果你想同时捕获标准错误输出,不要忘记将stderr流重定向到stdoutpython -u MyLongRunngingScript.py 2>&1 | tee log.txt。请注意,这里的log.txt是保存脚本输出的文件名。 - stephenfin

2
您看不到任何东西可能与缓冲有关。因此,您只会在每4 KB左右的文本输出一次。相反,请尝试像这样做:
class OutputSplitter(object):
    def __init__(self, real_output, *open_files):
        self.__stdout = real_output
        self.__fds = open_files
        self.encoding = real_output.encoding
    def write(self, string):
        self.__stdout.write(string) # don't catch exception on that one.
        self.__stdout.flush()
        for fd in self.__fds:
            try:
                fd.write(string)
                fd.flush()
            except IOError:
                pass # do what you want here. 
    def flush(self):
        pass # already flushed

接着,使用以下代码将sys.stdout装饰为这个类:

stdout_saved = sys.stdout
logfile = open("log.txt","a") # check exception on that one.
sys.stdout = OutputSplitter(stdout_saved, logfile)

那样,每个输出(包括print)都会刷新到标准输出和指定的文件中。由于我没有测试过该实现,可能需要进行调整。当打印消息时,预计会出现(大多数情况下很小的)性能损失。

2
另一个简单的解决方案也可以是:
python script.py > output.log

1
你可以尝试在脚本中偶尔使用sys.stdout.flush(),然后再次使用tee运行。当stdout被重定向到tee时,它可能会被缓冲更长的时间,而不是直接传输到终端。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接