Skip to content

Instantly share code, notes, and snippets.

@rshk
Last active May 20, 2018 04:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rshk/11398392 to your computer and use it in GitHub Desktop.
Save rshk/11398392 to your computer and use it in GitHub Desktop.
Python colorful logging example

Usage example

% python -i colorful_logging_formatter.py 
>>> import logging
>>> logger = logging.getLogger('foo')
>>> logger.setLevel(logging.DEBUG)
>>> import sys
>>> handler = logging.StreamHandler(sys.stderr)
>>> handler.setFormatter(ColorLogFormatter())
>>> handler.setLevel(logging.DEBUG)
>>> logger.addHandler(handler)
>>> 
>>> logger.debug('Debug message')
 DEBUG   foo  Debug message
>>> logger.info('Info message')
 INFO    foo  Info message
>>> logger.warning('Warning message')
 WARNING  foo  Warning message
>>> logger.error('Error message')
 ERROR   foo  Error message
>>> logger.critical('Critical message')
 CRITICAL  foo  Critical message
>>> try:
...     100 / 0
... except:
...     logger.exception('Something bad happened!')
... 
 ERROR   foo  Something bad happened!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero
>>> 

Screenshot

Screenshot

Note

To see it in all its glory, you'll need to use a powerline-patched font in your terminal (I use inconsolata-dz). Otherwise, just set POWERLINE_STYLE = False.

import logging
from termcolor import colored
POWERLINE_STYLE = True
class ColorLogFormatter(logging.Formatter):
level_colors = {
logging.DEBUG: 'cyan',
logging.INFO: 'green',
logging.WARNING: 'yellow',
logging.ERROR: 'red',
logging.CRITICAL: 'red',
}
def _get_exc_info(self, record):
if record.exc_info:
# Cache the traceback text to avoid converting it multiple times
# (it's constant anyway)
if not record.exc_text:
record.exc_text = self.formatException(record.exc_info)
if record.exc_text:
try:
return unicode(record.exc_text)
except UnicodeError:
# Sometimes filenames have non-ASCII chars, which can lead
# to errors when s is Unicode and record.exc_text is str
# See issue 8924.
# We also use replace for when there are multiple
# encodings, e.g. UTF-8 for the filesystem and latin-1
# for a script. See issue 13232.
return record.exc_text.decode(sys.getfilesystemencoding(),
'replace')
return None
def format(self, record):
"""Format logs nicely"""
color = self.level_colors.get(record.levelno, 'white')
levelname = colored(' {0:<6} '.format(record.levelname),
color, attrs=['reverse'])
if POWERLINE_STYLE:
levelname += colored(u'\ue0b0', color, 'on_white')
loggername = colored(' {0} '.format(record.name), 'red', 'on_white')
if POWERLINE_STYLE:
loggername += colored(u'\ue0b0', 'white')
message = colored(record.getMessage(), color)
s = ' '.join((''.join((levelname, loggername)), message))
exc_info = self._get_exc_info(record)
if exc_info is not None:
if s[-1:] != "\n":
s = s + "\n"
s += colored(exc_info, 'grey', attrs=['bold'])
return s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment