I am adding logging to a Python project, and I wish to log to both terminal and file. To do this I am using a streamHandler
and a fileHandler
.
To make it easier to quickly differentiate between log levels, I wish to add colour to the levelname
for the logs that are output to the terminal, and to achieve this I have added a filter.
However, despite the filter only being applied to the streamHandler
, messages in the log file are seeing the colour code applied. How can this be, given the filter is not added to the fileHandler
?
Example Code
Note that the filter in this example only includes a format for logging.ERROR
, as this will log to both terminal and file. But in reality I have a format for all log levels.
import loggingclass ColourLevelNameFilter(logging.Filter): FORMATS = { logging.ERROR: '\x1b[031m'+'{0}'+'\x1b[0m', } def filter(self, record): levelname_format = self.FORMATS.get(record.levelno) record.levelname = levelname_format.format(record.levelname) return Truedef main(): time_format = '%Y-%m-%d %H:%M:%S' text_format = '%(asctime)s %(levelname)s => %(message)s' formatter = logging.Formatter(text_format, time_format) stream_handler = logging.StreamHandler() stream_handler.setFormatter(formatter) stream_handler.setLevel(logging.INFO) stream_handler.addFilter(ColourLevelNameFilter()) log_file = 'test-error.log' file_handler = logging.FileHandler(log_file, 'w') file_handler.setFormatter(formatter) file_handler.setLevel(logging.WARNING) logger = logging.getLogger('my-app') logger.setLevel(logging.INFO) logger.addHandler(stream_handler) logger.addHandler(file_handler) logger.error('Testing logging of error.')if __name__ == '__main__': main()