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

Python 如何使用脚本将stdout重定向到文件和控制台?,python,python-2.7,Python,Python 2.7,我想运行一个python脚本,在文本文件中捕获输出,并在控制台上显示 我想将其指定为python脚本本身的属性。不要每次在命令提示符下使用命令echo“hello world”| tee test.txt 在脚本中,我尝试: sys.stdout = open('log.txt','w') 但这不会在屏幕上显示标准输出 我听说过日志模块,但使用该模块来完成这项工作时运气不佳。在执行python文件时,可以使用shell重定向: python foo_bar.py > file 这将把打

我想运行一个python脚本,在文本文件中捕获输出,并在控制台上显示

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

在脚本中,我尝试:

sys.stdout = open('log.txt','w')
但这不会在屏幕上显示标准输出


我听说过日志模块,但使用该模块来完成这项工作时运气不佳。

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

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"

这将向标准输出和日志文件写入“Hello”

我找到了将输出重定向到控制台以及同时重定向到文本文件的方法:

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)

您可以使用带有print rint的“V形”语法的>>python将输出重定向到文件,如中所示

让我想想

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您将获得数据
要在控制台上打印,只需使用普通打印语句。

要将输出重定向到文件和终端,而不修改Python脚本在外部的使用方式,可以使用
pty.spawn(自身)

如果
pty
模块(在Windows上)不可用,则您可以将其替换为更便携的模块,但它提供普通管道而不是伪终端,这可能会改变某些程序的行为


与使用类似文件的对象替换
sys.stdout
相比,基于
pty.spawn
subprocess.Popen
的解决方案的优势在于,它们可以在文件描述符级别捕获输出,例如,如果脚本启动其他进程,也可以在stdout/stderr上生成输出。请参阅我对相关问题的回答:

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

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

def printing(text):
    print text
    if args.Output_File:
        OF.write(text + "\n")
在此之后,将一行打印到文件和/或屏幕所需的全部内容是:
打印(要打印的行)

使用日志模块调试并跟踪应用程序

下面是我如何登录到文件和控制台/stdout的

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')
从以下来源阅读:

基于,这里有一个简单的模块,您可以使用它进行日志记录-

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

中的
Tee
类执行您想要的操作,但它缺少在
with
-语句中调用它所需的
\uuuuuuuuuuuuuuuuuu
方法。这些都是由添加的。

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

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()
要使用上下文管理器,请执行以下操作:

print("Print")
with Tee('test.txt'):
    print("Print+Write")
    raise Exception("Test")
print("Print")

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

这个解决方案使用了更多的计算能力,但可靠地将所有数据从标准输出保存到日志文件中,并且使用更少的内存。为了满足我的需要,我还在self.log.write(message)中添加了时间戳。非常好。

基于,我创建了一个更易于调用的类:

class Logger(object):

    """
    Class to log output of the command line to a log file

    Usage:
    log = Logger('logfile.log')
    print("inside file")
    log.stop()
    print("outside file")
    log.start()
    print("inside again")
    log.stop()
    """

    def __init__(self, filename):
        self.filename = filename

    class Transcript:
        def __init__(self, filename):
            self.terminal = sys.stdout
            self.log = open(filename, "a")
        def __getattr__(self, attr):
            return getattr(self.terminal, attr)
        def write(self, message):
            self.terminal.write(message)
            self.log.write(message)
        def flush(self):
            pass

    def start(self):
        sys.stdout = self.Transcript(self.filename)

    def stop(self):
        sys.stdout.log.close()
        sys.stdout = sys.stdout.terminal

这种方法在我的情况下非常有效。我刚刚添加了一些基于此线程中其他代码的修改

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()

嗨,Amith,我不想使用它,因为它需要手动交互来完成(>文件)。我是否也可以在脚本中做些什么,或者一旦执行完成,控制台上会出现什么,并将其推送到一个文件中???@user2033758:一旦退出程序,在控制台上执行完成,程序不再对它有任何控制。@user2033758:这个答案中有两个建议,第二个建议不需要任何手动交互。您可以使用命令行,也可以在代码中使用类。我对此进行了测试,该类将输出发送到控制台和文件,命令行上没有任何特殊参数。如何恢复正常的
sys.stdout
行为?假设我想要这个,但只是在程序的启动阶段,然后过了一段时间,我想让程序运行,但不保存everything@TokeFaurbyYou可以在Logger中保存以前的
sys.stdout
,并创建一个将其还原为原始状态的函数。
>
不是重定向运算符,是值班员。请更改此项。此项在python2.7中有效。>>可以与print语句一起使用,将字符串重定向到给定的文件对象。请通过自己尝试我的解决方案来验证使用自定义函数处理它的简单而出色的想法。这很有效。但是,请注意,“打印”功能的输入“文本”必须是显式文本。它不支持print支持的任何其他参数。我支持非显式文本(如datetime.datetime)的问题是在write函数中。我刚刚用
str(text)
将文本转换为字符串。回答得好!在Python3中,由于缺少“isatty”,我出现了一个错误。要修复此问题,请添加以下内容:def isatty(self):return false not cool复制粘贴其他人自己的答案ttps://stackoverflow.com/a/9321890/7646049 只需提供它们的参考。@EvgenyKuznetsov我发布了一个到python文档的链接,这是我复制的地方;你认为另一个stackoverflow答案可能是从同一个地方复制的吗?我运行了一个python进程,在
log.txt
文件中看不到数据,除非我终止该进程。看起来日志正在被缓冲,然后在最后被转储。您好@MukeshKumar,我也遇到了同样的问题。我在文件末尾添加了
te.flush()
,以强制它停止缓冲数据并写入。此外,我在删除数据时遇到问题,因为它仍然在a中打开
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()   
class Logger(object):

    """
    Class to log output of the command line to a log file

    Usage:
    log = Logger('logfile.log')
    print("inside file")
    log.stop()
    print("outside file")
    log.start()
    print("inside again")
    log.stop()
    """

    def __init__(self, filename):
        self.filename = filename

    class Transcript:
        def __init__(self, filename):
            self.terminal = sys.stdout
            self.log = open(filename, "a")
        def __getattr__(self, attr):
            return getattr(self.terminal, attr)
        def write(self, message):
            self.terminal.write(message)
            self.log.write(message)
        def flush(self):
            pass

    def start(self):
        sys.stdout = self.Transcript(self.filename)

    def stop(self):
        sys.stdout.log.close()
        sys.stdout = sys.stdout.terminal
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()