将stdout重定向到Python中的文件?

问题描述 投票:288回答:10

如何在Python中将stdout重定向到任意文件?

[当从ssh会话中启动并运行背景良好的Python脚本(例如,Web应用程序),并且关闭了ssh会话时,该应用程序将引发IOError并在尝试写入stdout时失败。我需要找到一种方法来使应用程序和模块输出到文件而不是stdout,以防止由于IOError而导致失败。当前,我使用nohup将输出重定向到文件,并且可以完成工作,但是出于好奇,我想知道是否存在一种无需使用nohup的方法。

我已经尝试过sys.stdout = open('somefile', 'w'),但是这似乎并不能阻止某些外部模块仍输出到终端(或者sys.stdout = ...行根本没有触发)。我知道它应该可以通过我测试过的简单脚本工作,但是我还没有时间在Web应用程序上进行测试。

python stdout
10个回答
369
投票

如果要在Python脚本中进行重定向,则将sys.stdout设置为文件对象可以解决问题:

import sys
sys.stdout = open('file', 'w')
print('test')

一种更普遍的方法是在执行时使用外壳重定向(在Windows和Linux上相同:]]

$ python foo.py > file

0
投票
用其他语言(例如C)编写的程序必须做特别的魔术(称为双叉),才能与终端分离(并防止僵尸进程)。因此,我认为最好的解决方案是模拟它们。

重新执行程序的好处是,您可以在命令行上选择重定向,例如stderr


151
投票

88
投票

您可以尝试做得更好


28
投票

其他答案未涵盖您希望分叉的进程共享新标准输出的情况。


27
投票

引自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 (添加的导入语句):


11
投票
import sys
from contextlib import contextmanager
@contextmanager
def stdout_redirected(new_stdout):
    save_stdout = sys.stdout
    sys.stdout = new_stdout
    try:
        yield None
    finally:
        sys.stdout = save_stdout

2
投票

基于此答案:with open(filename, "w") as f: with stdout_redirected(f): print "Hello world" ,这是我想出在我的一个项目中使用的另一种方法。对于用import sys sys.stdout = open('stdout.txt', 'w') https://stackoverflow.com/a/5916874/1060344替换的任何内容,都必须确保替换符合sys.stderr接口,尤其是在执行此操作时,因为stderr / stdout用于其他未在其中的库您的控制权。该库可能正在使用文件对象的其他方法。


2
投票

您需要像fileclass FileToLogInterface(file): ''' Interface to make sure that everytime anything is written to stderr, it is also forwarded to a file. ''' def __init__(self, *args, **kwargs): if 'cfg' not in kwargs: raise TypeError('argument cfg is required.') else: if not isinstance(kwargs['cfg'], config.Config): raise TypeError( 'argument cfg should be a valid ' 'PostSegmentation configuration object i.e. ' 'postsegmentation.config.Config') self._cfg = kwargs['cfg'] kwargs.pop('cfg') self._logger = logging.getlogger('access_log') super(FileToLogInterface, self).__init__(*args, **kwargs) def write(self, msg): super(FileToLogInterface, self).write(msg) self._logger.info(msg) 这样的终端多路复用器>

[令我惊讶的是,瑞安·阿莫斯(Ryan Amos)对原始问题的一小段评论是唯一提及的解决方案远胜于其他所有解决方案,无论python技巧多么聪明,以及他们进行了多少投票收到。除了Ryan的评论,tmux是GNU屏幕的不错选择。


1
投票
这里是

Yuda Prawira

的变体:答案:
© www.soinside.com 2019 - 2024. All rights reserved.