如何使用脚本将stdout重定向到文件和控制台?

问题描述:

我想运行一个python脚本并捕获文本文件上的输出以及想要在控制台上显示。如何使用脚本将stdout重定向到文件和控制台?

我想指定它作为python脚本本身的属性。每次不要在命令提示符下使用命令echo "hello world" | tee test.txt

在剧本我想:

sys.stdout = open('log.txt','w') 

但这并不在屏幕上显示标准输出输出。

我听说过有关日志记录模块,但我无法运用该模块来完成这项工作。

您可以使用shell重定向在执行Python文件:

python foo_bar.py > file 

这将写印刷在标准输出的所有结果从Python源提交到日志文件。

或者,如果你想从脚本内录入:

import sys 

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

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

    def flush(self): 
     #this flush method is needed for python 3 compatibility. 
     #this handles the flush command by doing nothing. 
     #you might want to specify some extra behavior here. 
     pass  

sys.stdout = Logger() 

现在你可以使用:

print "Hello" 

这会写“你好”到标准输出和日志文件

+1

嗨Amith,我不想使用它,因为它需要手动交互来执行此操作(>文件)。有没有什么我可以在脚本中完成,或者一旦执行完成,然后控制台上发生了什么,需要并推送到文件? – user2033758 2013-02-16 04:31:18

+0

@ user2033758:一旦执行完成后,它一旦离开程序并在控制台上,程序就不再有任何控制权。 – Anthon 2013-03-13 03:49:36

+1

@ user2033758:这个答案中有两个建议,第二个不需要任何手动交互。您可以使用命令行,也可以在代码中使用该类。我测试了这一点,这个类将输出发送到控制台和文件,在命令行上没有任何特殊参数。 – JDM 2013-05-04 10:49:02

我得到了将输出重定向到控制台以及文本文件的方式:

te = open('log.txt','w') # File where you need to keep the logs 

class Unbuffered: 

    def __init__(self, stream): 

     self.stream = stream 

    def write(self, data): 

     self.stream.write(data) 
     self.stream.flush() 
     te.write(data) # Write the data of stdout here to a text file as well 



sys.stdout=Unbuffered(sys.stdout) 

可以作为docs

指示的输出通过使用>>带有打印RINT的“人字形”语法蟒蛇重定向到文件让看,

fp=open('test.log','a') # take file object reference 
print >> fp , "hello world"   #use file object with in print statement. 
print >> fp , "every thing will redirect to file " 
fp.close() #close the file 

结账文件test.log中你将有数据 并在控制台上打印只需使用明码声明。

+1

'>>'不是重定向操作符,它是移位操作符。请改变这一点。 – nbro 2015-01-06 21:19:59

将输出重定向到一个文件,而无需修改您的Python脚本是如何使用外部的终端,你可以使用pty.spawn(itself)

#!/usr/bin/env python 
"""Redirect stdout to a file and a terminal inside a script.""" 
import os 
import pty 
import sys 

def main(): 
    print('put your code here') 

if __name__=="__main__": 
    sentinel_option = '--dont-spawn' 
    if sentinel_option not in sys.argv: 
     # run itself copying output to the log file 
     with open('script.log', 'wb') as log_file: 
      def read(fd): 
       data = os.read(fd, 1024) 
       log_file.write(data) 
       return data 

      argv = [sys.executable] + sys.argv + [sentinel_option] 
      rc = pty.spawn(argv, read) 
    else: 
     sys.argv.remove(sentinel_option) 
     rc = main() 
    sys.exit(rc) 

如果pty模块不可用(在Windows上),那么你可以取代它与teed_call() function这是更便携,但它提供了普通的管道,而不是一个伪终端 - 它可能会改变一些程序的行为。

超过与一个类文件对象替换sys.stdoutpty.spawnsubprocess.Popen系溶液的优点是,它们能够捕获至少一个文件描述符水平例如输出,如果脚本将启动也可以在stdout产生输出其他进程/标准错误。看到我对相关问题的回答:Redirect stdout to a file in Python?

我设计了一个更简单的解决方案。只需定义一个将打印到文件或屏幕或两者的函数。在下面的例子中我允许用户输入OUTPUTFILE名作为参数但这不是强制性的:

OutputFile= args.Output_File 
OF = open(OutputFile, 'w') 

def printing(text): 
    print text 
    if args.Output_File: 
     OF.write(text + "\n") 

在此之后,所有需要以打印线既文件和/或屏幕是: 印刷(Line_to_be_printed)

+0

用自定义功能处理它的简单而绝妙的想法。 – Akif 2017-08-31 08:05:24

使用记录模块调试,并按照您的应用程序

这是我如何成功地记录到文件,并安慰/标准输出

import logging 
logging.basicConfig(level=logging.INFO, 
        format='%(asctime)s - %(levelname)s - %(message)s', 
        filename='logs_file', 
        filemode='w') 
# Until here logs only to file: 'logs_file' 

# define a new Handler to log to console as well 
console = logging.StreamHandler() 
# optional, set the logging level 
console.setLevel(logging.INFO) 
# set a format which is the same for console use 
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') 
# tell the handler to use this format 
console.setFormatter(formatter) 
# add the handler to the root logger 
logging.getLogger('').addHandler(console) 

# Now, we can log to both ti file and console 
logging.info('Jackdaws love my big sphinx of quartz.') 
logging.info('Hello world') 

从源代码阅读: https://docs.python.org/2/howto/logging-cookbook.html

基于Amith Koujalgi's answer,这里有一个简单的模块,您可以使用日志 -

transcript.py:

""" 
Transcript - direct print output to a file, in addition to terminal. 

Usage: 
    import transcript 
    transcript.start('logfile.log') 
    print("inside file") 
    transcript.stop() 
    print("outside file") 
""" 

import sys 

class Transcript(object): 

    def __init__(self, filename): 
     self.terminal = sys.stdout 
     self.logfile = open(filename, "a") 

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

    def flush(self): 
     # this flush method is needed for python 3 compatibility. 
     # this handles the flush command by doing nothing. 
     # you might want to specify some extra behavior here. 
     pass 

def start(filename): 
    """Start transcript, appending print output to given filename""" 
    sys.stdout = Transcript(filename) 

def stop(): 
    """Stop transcript and return print functionality to normal""" 
    sys.stdout.logfile.close() 
    sys.stdout = sys.stdout.terminal 

我尝试这样做:

""" 
Transcript - direct print output to a file, in addition to terminal. 

Usage: 
    import transcript 
    transcript.start('logfile.log') 
    print("inside file") 
    transcript.stop() 
    print("outside file") 
""" 

import sys 

class Transcript(object): 

    def __init__(self, filename): 
     self.terminal = sys.stdout, sys.stderr 
     self.logfile = open(filename, "a") 

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

    def flush(self): 
     # this flush method is needed for python 3 compatibility. 
     # this handles the flush command by doing nothing. 
     # you might want to specify some extra behavior here. 
     pass 

def start(filename): 
    """Start transcript, appending print output to given filename""" 
    sys.stdout = Transcript(filename) 

def stop(): 
    """Stop transcript and return print functionality to normal""" 
    sys.stdout.logfile.close() 
    sys.stdout = sys.stdout.terminal 
    sys.stderr = sys.stderr.terminal 

from IPython.utils.io import Tee 
from contextlib import closing 

print('This is not in the output file.')   

with closing(Tee("outputfile.log", "w", channel="stdout")) as outputstream: 
    print('This is written to the output file and the console.') 
    # raise Exception('The file "outputfile.log" is closed anyway.') 
print('This is not written to the output file.') 

# Output on console: 
# This is not in the output file. 
# This is written to the output file and the console. 
# This is not written to the output file. 

# Content of file outputfile.txt: 
# This is written to the output file and the console. 

The在IPython.utils.io中的类可以做你想做的,但是它缺少__enter____exit__方法,在with-声明中调用它。那些被contextlib.closing加上。