如何在Python中将标准输出重定向到任意文件?

When a long-running Python script (e.g, web application) is started from within the ssh session and backgounded, and the ssh session is closed, the application will raise IOError and fail the moment it tries to write to stdout. I needed to find a way to make the application and modules output to a file rather than stdout to prevent failure due to IOError. Currently, I employ nohup to redirect output to a file, and that gets the job done, but I was wondering if there was a way to do it without using nohup, out of curiosity.

我已经试过了。Stdout = open('somefile', 'w'),但这似乎并没有阻止一些外部模块仍然输出到终端(或者sys. exe)。Stdout =…Line根本没有开火)。我知道它应该在我测试过的更简单的脚本上工作,但我还没有时间在web应用程序上进行测试。


当前回答

用其他语言(例如C)编写的程序必须使用特殊的魔法(称为双分叉)来明确地与终端分离(并防止僵尸进程)。所以,我认为最好的解决办法是模仿他们。

重新执行程序的一个好处是,你可以在命令行上选择重定向,例如/usr/bin/python mycoolscript.py 2>&1 1>/dev/null

查看这篇文章了解更多信息:在创建守护进程时执行双fork的原因是什么?

其他回答

你可以尝试更好的方法

import sys

class Logger(object):
    def __init__(self, filename="Default.log"):
        self.terminal = sys.stdout
        self.log = open(filename, "a")

    def write(self, message):
        self.terminal.write(message)
        self.log.write(message)

sys.stdout = Logger("yourlogfilename.txt")
print "Hello world !" # this is should be saved in yourlogfilename.txt

基于这篇文章之前的回答,我为自己编写了这个类,作为一种更紧凑和灵活的方式来重定向代码段的输出——这里只是一个列表——并确保之后的输出是规范化的。

class out_to_lt():
    def __init__(self, lt):
        if type(lt) == list:
            self.lt = lt
        else:
            raise Exception("Need to pass a list")            
    def __enter__(self):
        import sys
        self._sys = sys
        self._stdout = sys.stdout
        sys.stdout = self
        return self
    def write(self,txt):
        self.lt.append(txt)    
    def __exit__(self, type, value, traceback):
        self._sys.stdout = self._stdout

用作:

lt = []
with out_to_lt(lt) as o:
    print("Test 123\n\n")
    print(help(str))

更新。刚刚发现了一个场景,我必须添加两个额外的方法,但很容易适应:

class out_to_lt():
    ...
    def isatty(self):
        return True #True: You're running in a real terminal, False:You're being piped, redirected, cron
    def flush(self):
        pass

如果您想在Python脚本中进行重定向,请设置sys. exe。对文件对象的Stdout是有用的:

# for python3
import sys
with open('file', 'w') as sys.stdout:
    print('test')

一个更常见的方法是在执行时使用shell重定向(在Windows和Linux上相同):

$ python3 foo.py > file

我知道这个问题已经得到了回答(使用python abc.py > output.log 2>&1),但我仍然不得不说:

在编写程序时,不要写入标准输出。总是使用日志来输出您想要的任何东西。这在以后你想重定向,过滤,旋转输出文件的时候会给你很大的自由。

用其他语言(例如C)编写的程序必须使用特殊的魔法(称为双分叉)来明确地与终端分离(并防止僵尸进程)。所以,我认为最好的解决办法是模仿他们。

重新执行程序的一个好处是,你可以在命令行上选择重定向,例如/usr/bin/python mycoolscript.py 2>&1 1>/dev/null

查看这篇文章了解更多信息:在创建守护进程时执行双fork的原因是什么?