如何使用脚本将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"
这会写“你好”到标准输出和日志文件
我得到了将输出重定向到控制台以及文本文件的方式:
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中你将有数据 并在控制台上打印只需使用明码声明。
'>>'不是重定向操作符,它是移位操作符。请改变这一点。 – 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.stdout
pty.spawn
和subprocess.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)
用自定义功能处理它的简单而绝妙的想法。 – 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
加上。
嗨Amith,我不想使用它,因为它需要手动交互来执行此操作(>文件)。有没有什么我可以在脚本中完成,或者一旦执行完成,然后控制台上发生了什么,需要并推送到文件? – user2033758 2013-02-16 04:31:18
@ user2033758:一旦执行完成后,它一旦离开程序并在控制台上,程序就不再有任何控制权。 – Anthon 2013-03-13 03:49:36
@ user2033758:这个答案中有两个建议,第二个不需要任何手动交互。您可以使用命令行,也可以在代码中使用该类。我测试了这一点,这个类将输出发送到控制台和文件,在命令行上没有任何特殊参数。 – JDM 2013-05-04 10:49:02