Reputation: 47
I have set up a class of colours to make the stdout easier to read in case of warnings. I also want to write all print statements to a log file.
# Colour set up
class colours:
warning = '\033[93m'
colour1 = '\033[94m'
colour2 = '\033[1m'
terminate = '\033[0m'
# Logger set up
class Logger(object):
def __init__(self):
self.terminal = sys.stdout
self.log = open(“output.log”, "a")
def write(self, message):
self.terminal.write(message)
self.log.write(message)
sys.stdout = Logger()
# Example
print colours.warning + ‘WARNING!’ + colours.terminate
*in colour*:$ WARNING!
*in output.log*: [93mWARNING!
Is there any way to either write characters that will also colour the output.log file or print in colour to the stdout but not include '[94m' in the log file? I’d prefer not to require an install of any non-native python packages for user ease.
Upvotes: 3
Views: 3505
Reputation: 91
I know, that is an old thread, but I want to leave my improved (in my mind) solution of @AKX for other people.
To automate what was done when logging, i.e. re.sub(...)
one can create a custom formatter.
class TermEscapeCodeFormatter(logging.Formatter):
"""A class to strip the escape codes from the """
def __init__(self, fmt=None, datefmt=None, style='%', validate=True):
super().__init__(fmt, datefmt, style, validate)
def format(self, record):
escape_re = re.compile(r'\x1b\[[0-9;]*m')
record.msg = re.sub(escape_re, "", str(record.msg))
return super().format(record)
Then I set it as a Formatter
for a particular FileHandler
.
def main():
lger = logging.getLogger("test_hw")
lger.setLevel(logging.INFO)
stdo = logging.StreamHandler()
stdo.setLevel(logging.INFO)
fhdr = logging.FileHandler("fname.txt", "w")
fhdr.setLevel(logging.INFO)
fmer = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
stdo.setFormatter(fmer)
cfmer = TermEscapeCodeFormatter('%(asctime)s - %(levelname)s - %(message)s')
fhdr.setFormatter(cfmer)
lger.addHandler(stdo)
lger.addHandler(fhdr)
Now one can use one logger with coloring (I use Colorama) to output to stdout with the colors enabled and to file with them disabled.
lger.info(f"value = {Style.BRIGHT}{value :>5.2f} V{Style.RESET_ALL}")
In this version works only for ANSI terminals, but one could adapt the regexp to match other patterns.
There is no defaults
keyword argument as per newest (3.10 I believe) Python version. I use 3.8.
Upvotes: 1
Reputation: 168913
Use a regexp like \x1b\[[0-9;]*m
to strip out the ANSI codes when writing to the output.log
object?
I.e.
import re
ansi_re = re.compile(r'\x1b\[[0-9;]*m')
# ...
self.log.write(re.sub(ansi_re, '', message))
Upvotes: 3