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

use*_*758 60 python-2.7

我想运行一个python脚本并捕获文本文件的输出以及想要在控制台上显示.

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

在脚本中我试过:

sys.stdout = open('log.txt','w')
Run Code Online (Sandbox Code Playgroud)

但是这并没有在屏幕上显示stdout输出.

我听说过记录模块,但是我无法使用该模块来完成这项工作.

Ami*_*lgi 106

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

python foo_bar.py > file
Run Code Online (Sandbox Code Playgroud)

这会将stdout上打印的所有结果从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()
Run Code Online (Sandbox Code Playgroud)

现在你可以使用:

print "Hello"
Run Code Online (Sandbox Code Playgroud)

这将向stdout和日志文件写入"Hello"

  • @UmairAyub如果你还想要python错误日志记录,只需在`sys.stdout = Logger()`之后添加`sys.stderr = sys.stdout` (2认同)

use*_*758 18

我有办法将输出重定向到控制台以及文本文件同时:

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)
Run Code Online (Sandbox Code Playgroud)

  • 你好@MukeshKumar,我也遇到了同样的问题。我将“te.flush()”添加到文件末尾,以强制它停止缓冲数据并写入数据。另外,我在删除数据时遇到了问题,因为它仍然在应用程序中打开,所以我添加了“te.close()”。第三个问题是,我在 Jupyter 中的单元会无限期地运行,直到我杀死内核。我通过捕获 stdout 的原始状态(`orig_stdout = sys.stdout`)并在脚本末尾再次分配它(`sys.stdout = orig_stdout`)来解决它。之后,一切都进展顺利。 (3认同)

Rad*_*iel 14

使用日志记录模块调试并关注您的应用

以下是我设法登录文件和控制台/标准输出的方法

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')
Run Code Online (Sandbox Code Playgroud)

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

  • @EvgenyKuznetsov 我发布了一个 python 文档的链接,这是我复制的地方;您是否认为其他 stackoverflow 答案可能是从同一个地方复制的? (3认同)

小智 10

我设计了一个更简单的解决方案 只需定义一个将打印到文件或屏幕或两者都打印的功能.在下面的示例中,我允许用户输入outputfile名称作为参数,但这不是必需的:

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

def printing(text):
    print text
    if args.Output_File:
        OF.write(text + "\n")
Run Code Online (Sandbox Code Playgroud)

在此之后,在文件和/或屏幕上打印行所需的全部内容是:打印(Line_to_be_printed)

  • 这有效。但是,请注意,“打印”功能的输入“文本”必须是明确的文本。它不支持 print 支持的任何其他参数。 (2认同)

小智 8

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.
Run Code Online (Sandbox Code Playgroud)

Tee在课堂上IPython.utils.io你想要做什么,但它缺乏__enter____exit__调用它在需要的方法with语句来。这些是由contextlib.closing.


Bri*_*rns 7

根据Amith Koujalgi的回答,这是一个可用于记录日志的简单模块-

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
Run Code Online (Sandbox Code Playgroud)


sup*_*ver 5

这是一个简单的上下文管理器,它打印到控制台并将相同的输出写入文件。它还将任何异常写入文件。

import traceback
import sys

# Context manager that copies stdout and any exceptions to a log file
class Tee(object):
    def __init__(self, filename):
        self.file = open(filename, 'w')
        self.stdout = sys.stdout

    def __enter__(self):
        sys.stdout = self

    def __exit__(self, exc_type, exc_value, tb):
        sys.stdout = self.stdout
        if exc_type is not None:
            self.file.write(traceback.format_exc())
        self.file.close()

    def write(self, data):
        self.file.write(data)
        self.stdout.write(data)

    def flush(self):
        self.file.flush()
        self.stdout.flush()
Run Code Online (Sandbox Code Playgroud)

要使用上下文管理器:

print("Print")
with Tee('test.txt'):
    print("Print+Write")
    raise Exception("Test")
print("Print")
Run Code Online (Sandbox Code Playgroud)


San*_*kov 5

我在这里尝试了一些解决方案,但没有找到同时写入文件和控制台的解决方案。所以这就是我所做的(基于这个答案)

class Logger(object):
    def __init__(self):
        self.terminal = sys.stdout

    def write(self, message):
        with open ("logfile.log", "a", encoding = 'utf-8') as self.log:            
            self.log.write(message)
        self.terminal.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()   
Run Code Online (Sandbox Code Playgroud)

该解决方案使用更多的计算能力,但可靠地将所有来自标准输出的数据保存到记录器文件中,并使用更少的内存。为了我的需要,我还在 self.log.write(message) 中添加了时间戳。效果很好。


Arn*_*uza 5

这种方法在我的情况下非常有效。我只是根据该线程中提供的其他代码添加了一些修改。

import sys, os 

orig_stdout = sys.stdout  # capture original state of stdout

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)




#######################################
##  Feel free to use print function  ##
#######################################

print("Here is an Example =)")

#######################################
##  Feel free to use print function  ##
#######################################




# Stop capturing printouts of the application from Windows CMD
sys.stdout = orig_stdout  # put back the original state of stdout
te.flush()  # forces python to write to file
te.close()  # closes the log file

# read all lines at once and capture it to the variable named sys_prints
with open('log.txt', 'r+') as file:
    sys_prints = file.readlines() 

# erase the file contents of log file
open('log.txt', 'w').close()
Run Code Online (Sandbox Code Playgroud)