I can't figure out how to log info-level messages to stdout, but everything else to stderr. I already read this http://docs.python.org/library/logging.html. Any suggestion?
I can't figure out how to log info-level messages to stdout, but everything else to stderr. I already read this http://docs.python.org/library/logging.html. Any suggestion?
Simplest handler to send colored output to stderr:
class ColorStderr(logging.StreamHandler):
def __init__(self):
class AddColor(logging.Formatter):
def format(self, record: logging.LogRecord):
msg = super().format(record)
# Green/Cyan/Yellow/Red/Redder based on log level:
color = '\033[1;' + ('32m', '36m', '33m', '31m', '41m')[
min(4,int(4 * record.levelno / logging.FATAL))]
return color + record.levelname + '\033[1;0m: ' + msg
super().__init__(sys.stderr)
self.setFormatter(AddColor())
Use with:
logging.basicConfig(level=logging.INFO, handlers=[ColorStderr()])
Or you can even apply the formatter directly to the current log handler, with no need for ColorStderr:
logging.getLogger().handlers[0].setFormatter(AddColor())
Here is my answer (combination of the others):
logger = logging.getLogger(__name__)
class LogFilter(logging.Filter):
def __init__(self, level):
self.level = level
def filter(self, record):
return record.levelno < self.level
info_handler = logging.StreamHandler(stdout)
error_handler = logging.StreamHandler(stderr)
info_handler.addFilter(LogFilter(logging.WARNING))
error_handler.setLevel(max(logging.DEBUG, logging.WARNING))
logger.handlers = [info_handler, error_handler]
logger.setLevel(logging.DEBUG)
Try This Monkey Patch ~~
import sys
import logging
import threading
def _logging_handle(self, record):
self.STREAM_LOCKER = getattr(self, "STREAM_LOCKER", threading.RLock())
if self.stream in (sys.stdout, sys.stderr) and record.levelname in self.FIX_LEVELS:
try:
self.STREAM_LOCKER.acquire()
self.stream = sys.stdout
self.old_handle(record)
self.stream = sys.stderr
finally:
self.STREAM_LOCKER.release()
else:
self.old_handle(record)
def patch_logging_stream(*levels):
"""
writing some logging level message to sys.stdout
example:
patch_logging_stream(logging.INFO, logging.DEBUG)
logging.getLogger('root').setLevel(logging.DEBUG)
logging.getLogger('root').debug('test stdout')
logging.getLogger('root').error('test stderr')
"""
stream_handler = logging.StreamHandler
levels = levels or [logging.DEBUG, logging.INFO]
stream_handler.FIX_LEVELS = [logging.getLevelName(i) for i in levels]
if hasattr(stream_handler, "old_handle"):
stream_handler.handle = stream_handler.old_handle
stream_handler.old_handle = stream_handler.handle
stream_handler.handle = _logging_handle
Test
#
patch_logging_stream(logging.INFO, logging.DEBUG)
logging.getLogger('root').setLevel(logging.DEBUG)
logging.getLogger('root').debug('test root stdout')
logging.getLogger('root').error('test root stderr')
Test Output
$ python3 test_patch_logging.py 2>/dev/null
DEBUG:root:test root stdout
$ python3 test_patch_logging.py 1>/dev/null
ERROR:root:test root stderr