如何在Python中将stdout重定向到任意文件?
[当从ssh会话中启动并运行背景良好的Python脚本(例如,Web应用程序),并且关闭了ssh会话时,该应用程序将引发IOError并在尝试写入stdout时失败。我需要找到一种方法来使应用程序和模块输出到文件而不是stdout,以防止由于IOError而导致失败。当前,我使用nohup将输出重定向到文件,并且可以完成工作,但是出于好奇,我想知道是否存在一种无需使用nohup的方法。
我已经尝试过sys.stdout = open('somefile', 'w')
,但是这似乎并不能阻止某些外部模块仍输出到终端(或者sys.stdout = ...
行根本没有触发)。我知道它应该可以通过我测试过的简单脚本工作,但是我还没有时间在Web应用程序上进行测试。
如果要在Python脚本中进行重定向,则将sys.stdout
设置为文件对象可以解决问题:
import sys
sys.stdout = open('file', 'w')
print('test')
一种更普遍的方法是在执行时使用外壳重定向(在Windows和Linux上相同:]]
$ python foo.py > file
重新执行程序的好处是,您可以在命令行上选择重定向,例如stderr
[Python 3.4中有contextlib.redirect_stdout()
function:
您可以尝试做得更好
其他答案未涵盖您希望分叉的进程共享新标准输出的情况。
引自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
(添加的导入语句):
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
基于此答案: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用于其他未在其中的库您的控制权。该库可能正在使用文件对象的其他方法。
您需要像file
或class 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屏幕的不错选择。
Yuda Prawira
的变体:答案: