I want to print to console and a file at the same time. Following the examples in Stackoverflow question I managed to get it working with:
class DoublePrint(object):
def __init__(self, filename):
self.stream = sys.stdout
self.logfile = open(filename, 'w') # File for logging
def __enter__(self):
sys.stdout = self
def __exit__(self, exc_type, exc_value, traceback):
sys.stdout = self.orig_stdout
self.logfile.close()
def write(self, data):
self.stream.write(data)
self.logfile.write(data)
self.flush()
def flush(self):
self.stream.flush()
self.logfile.flush()
print("Only console 1")
with DoublePrint('pyLog.log'):
print("To both console and file")
print("Only console 2")
This prints to console:
Only console 1
To both console and file
Only console 2
And in the file "pyLog.log":
To both console and file
This is exactly what I want.
However, when I try to add a timestamp to data in the write-method, I get double prints of timestamp. And I don't understand why this is, and how to make it right.
def write(self, data):
output = subprocess.run(["date", " %H:%M:%S"], capture_output=True, text=True)
toprint = output.stdout.strip() data
self.stream.write( toprint )
self.logfile.write( toprint )
self.flush()
Produces the following output in the console:
Only console 1
17:23:09To both console and file17:23:09
Only console 2
Why do I get the time in the end too? And how do I avoid it?
CodePudding user response:
The issue comes from the fact that print
calls write
on sys.output
twice, once with data="To both console and file"
, once with data="\n"
, which explains the observed behavior. If you want to automatically add dates, you should instead keep track of if a date has already been inserted in this line.
By the way, in python 3 (which I assume you are using, since it's one of the tags) you don't need to explicitly inherit from object
. You can simply write
class DoublePrinter:
[...]
CodePudding user response:
Here's a way to do it, building on the answer by @BlackBeans (which pointed out that print()
calls write()
twice: once for its argument and a second time for '\n'
) and substituting platform independent Python logic to print the date:
import sys
import subprocess
import datetime
class DoublePrint:
def __init__(self, filename):
self.stream = sys.stdout
self.logfile = open(filename, 'w') # File for logging
def __enter__(self):
sys.stdout = self
def __exit__(self, exc_type, exc_value, traceback):
#sys.stdout = self.orig_stdout
sys.stdout = self.stream
self.logfile.close()
def writex(self, data):
self.stream.write(data)
self.logfile.write(data)
self.flush()
def write(self, data):
'''
output = subprocess.run(["date", " %H:%M:%S"], capture_output=True, text=True)
toprint = output.stdout.strip() data
'''
toprint = data if data == '\n' else datetime.datetime.now().strftime("%H:%M:%S ") data
self.stream.write( toprint )
self.logfile.write( toprint )
self.flush()
def flush(self):
self.stream.flush()
self.logfile.flush()
print("Only console 1")
with DoublePrint('pyLog.log'):
print("To both console and file")
print("Only console 2")
Output:
Only console 1
13:26:19 To both console and file
Only console 2