可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want to run a python script and capture the output on a text file as well as want to show on console.
I want to specify it as a property of the python script itself. NOT to use the command echo "hello world" | tee test.txt
on command prompt every time.
Within script I tried:
sys.stdout = open('log.txt','w')
But this does not show the stdout output on screen.
I have heard about logging module but I could not get luck using that module to do the job.
回答1:
You can use shell redirection while executing the python file:
python foo_bar.py > file
This will write all results being printed on stdout from the python source to file to the logfile.
Or if you want logging from within the script:
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()
Now you can use:
print "Hello"
This will write "Hello" to both stdout and the logfile
回答2:
I got the way to redirect the out put to console as well as to a text file as well simultaneously:
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)
回答3:
Use logging module to debug and follow your app
Here is how I managed to log to file and to console / 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')
read it from source:
https://docs.python.org/2/howto/logging-cookbook.html
回答4:
I devised an easier solution. Just define a function that will print to file or to screen or to both of them. In the example below I allow the user to input the outputfile name as an argument but that is not mandatory:
OutputFile= args.Output_File
OF = open(OutputFile, 'w')
def printing(text):
print text
if args.Output_File:
OF.write(text + "\n")
After this, all that is needed to print a line both to file and/or screen is:
printing(Line_to_be_printed)
回答5:
Based on Amith Koujalgi's answer, here's a simple module you can use for logging -
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
回答6:
To redirect output to a file and a terminal without modifying how your Python script is used outside, you could use 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)
If pty
module is not available (on Windows) then you could replace it with teed_call()
function that is more portable but it provides ordinary pipes instead of a pseudo-terminal -- it may change behaviour of some programs.
The advantage of pty.spawn
and subprocess.Popen
-based solutions over replacing sys.stdout
with a file-like object is that they can capture the output at a file descriptor level e.g., if the script starts other processes that can also produce output on stdout/stderr. See my answer to the related question: Redirect stdout to a file in Python?
回答7:
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 Tee
class in IPython.utils.io
does what you want, but it lacks the __enter__
and __exit__
methods needed to call it in the with
-statement. Those are added by contextlib.closing
.
回答8:
I tried this:
"""
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
回答9:
you can redirect the output to a file by using >> python with print rint's "chevron" syntax as indicated in the docs
let see,
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
checkout the file test.log you will have the data
and to print on console just use plain print statement .