Python Logging in Color

Every Python programmer still using print statements should up their game and migrate to the Python logging module. That module lets you filter output based on severity settings, lets you send the output to different destinations, and lets you format and structure your output.  

This formatting ability lets us create more regular and human-readable output.  A classic developer experience use case for this is to color code the output by severity level.  The following output shows 3 different logging levels in three different colors, INFO, WARNING and CRITICAL.


The same output also shows an arrangement that includes: time formatting, module name, level and a logging message.

Show me the code!

We only need 2 lines of code

    root_logger = logging.getLogger()
    CustomFormatter().replace_formatter(root_logger)


when we use this class derived from a thread on stackoverflow and other places.


import logging

class CustomFormatter(logging.Formatter):

    grey = "\x1b[38;20m"
    yellow = "\x1b[33;20m"
    red = "\x1b[31;20m"
    bold_red = "\x1b[31;1m"
    white = "\x1b[37m;20m"
    light_purple = "\x1b[94m"
    reset = "\x1b[0m"
    format = "%(asctime)s - %(name)30s - %(levelname)8s - %(message)s (%(filename)s:%(lineno)d)"

    # https://talyian.github.io/ansicolors/
    FORMATS = {
        logging.DEBUG: light_purple + format + reset,
        logging.INFO: grey + format + reset,
        logging.WARNING: yellow + format + reset,
        logging.ERROR: red + format + reset,
        logging.CRITICAL: bold_red + format + reset,
    }

    def format(self, record):
        log_fmt = self.FORMATS.get(record.levelno)
        formatter = logging.Formatter(log_fmt)
        return formatter.format(record)

    def replace_formatter(self, root_logger):
        """
        replace the current formatters with this one
        logger is the where we want the formatter to start, usually the root logger
        """

        # create console handler with a higher log level
        handler = logging.StreamHandler()
        handler.setFormatter(CustomFormatter())
        root_logger.handlers = []
        root_logger.addHandler(handler)

Disclaimer

This blog isn't new information. It exists as a placeholder so I don't forget in the future.

Revision History

Created 2023 04




Comments

Popular posts from this blog

Understanding your WSL2 RAM and swap - Changing the default 50%-25%

Installing the RNDIS driver on Windows 11 to use USB Raspberry Pi as network attached

DNS for Azure Point to Site (P2S) VPN - getting the internal IPs