我想运行一个python脚本并捕获文本文件的输出,并希望在控制台上显示。
我想将它指定为python脚本本身的属性。不要每次都在命令提示符上使用命令echo "hello world" | tee test.txt
。
在脚本中我试过:
sys.stdout = open('log.txt','w')
但这并没有在屏幕上显示stdout输出。
我听说过记录模块但我无法使用该模块来完成这项工作。
答案 0 :(得分:97)
执行python文件时可以使用shell重定向:
python foo_bar.py > file
这会将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()
现在你可以使用:
print "Hello"
这将为stdout和日志文件
写入“Hello”答案 1 :(得分:14)
我有办法将输出重定向到控制台以及同时重定向到文本文件:
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)
答案 2 :(得分:11)
使用日志记录模块调试并关注您的应用
以下是我如何设法登录文件和控制台/标准输出
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
答案 3 :(得分:9)
我设计了一个更简单的解决方案。只需定义一个将打印到文件或屏幕或两者都打印的功能。在下面的示例中,我允许用户输入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)
答案 4 :(得分:4)
基于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
答案 5 :(得分:2)
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.
IPython.utils.io
中的Tee
课做了你想要的,但缺少在__enter__
声明中调用它所需的__exit__
和with
方法。这些是contextlib.closing
添加的。
答案 6 :(得分:1)
这种方式在我的情况下非常有效。我只是根据此线程中提供的其他代码添加了一些修改。
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()
答案 7 :(得分:0)
要将输出重定向到文件和终端而不修改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替换它,它更便携但是它提供普通管道而不是伪终端 - 它可能会改变行为一些程序。
基于pty.spawn
和subprocess.Popen
的解决方案优于使用类文件对象替换sys.stdout
的优势在于它们可以在文件描述符级别捕获输出,例如,如果脚本启动其他进程,也可以在stdout / stderr上生成输出。请参阅我对相关问题的回答:Redirect stdout to a file in Python?
答案 8 :(得分:0)
这是一个简单的上下文管理器,可打印到控制台并将相同的输出写入文件。还将所有异常写入文件。
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")
答案 9 :(得分:0)
我在这里尝试了几种解决方案,但没有找到同时写入文件和控制台的解决方案。这就是我所做的(based on this answer)
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()
此解决方案使用更多的计算能力,但可靠地将所有数据从标准输出保存到记录器文件中,并使用较少的内存。为了我的需要,我也将时间戳添加到self.log.write(message)中。效果很好。
答案 10 :(得分:0)
基于Brian Burns edited answer,我创建了一个易于调用的类:
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
答案 11 :(得分:-2)
我试过了:
"""
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
答案 12 :(得分:-6)
您可以使用>>将输出重定向到文件python与print rint的“chevron”语法,如docs
中所示让我们看看,
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,你将获得数据 并在控制台上打印只需使用普通打印语句。