Python Logging: A Better Way to Format Messages

To set the stage: what is logging? Well, it’s essentially a way for you to keep track of what’s happening in your code without having to sift through endless lines of output. It allows you to log information at different levels (debug, info, warning, error, critical) and send that information to various destinations like the console or a file.

Now, formatting messages. By default, logging will print out your message in a pretty boring format: ` `. But who wants boring? Let’s spice it up! To do this, you can create a custom logger and handler that formats the output to your liking.

Here’s an example of how to set up logging with some fancy formatting:

# Import the necessary modules
import logging # Import the logging module to enable logging functionality
from datetime import datetime # Import the datetime module to access current date and time

# Set up our logger and handler
logger = logging.getLogger(__name__) # Create a custom logger with the name of the current module
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') # Create a custom format for the log messages
handler = logging.FileHandler('my_logfile.txt', mode='w') # Create a file handler to write the log messages to a file
handler.setLevel(logging.DEBUG) # Set the log level for the handler to DEBUG
handler.setFormatter(formatter) # Set the formatter for the handler to the custom format created above
logger.addHandler(handler) # Add the handler to the logger

# Set up our log levels and messages
logger.debug("This is a debug message") # Log a debug message
logger.info("This is an info message") # Log an info message
logger.warning("This is a warning message") # Log a warning message
logger.error("This is an error message") # Log an error message
logger.critical("This is a critical message") # Log a critical message

In this example, we’re creating a logger and handler for our custom log messages. We’re using the `datetime` module to format the date and time of each message, and then printing out the level name (debug, info, warning, error, or critical) followed by the actual message.

You can also configure logging through a configuration file or dictionary if you prefer not to set it up in your code. This is especially useful for larger projects where you may want to change your logging settings on the fly without having to restart your application.

Here’s an example of how to load a configuration from a YAML file:

# Import necessary libraries
import yaml # Importing the yaml library to load the configuration file
import logging # Importing the logging library to set up our logger and handler

# Load our configuration from a YAML file
with open('logging_config.yaml') as f: # Opening the logging configuration file
    config = yaml.load(f, Loader=yaml.FullLoader) # Loading the configuration using the yaml library and assigning it to the variable 'config'

# Set up our logger and handler using the loaded configuration
logger = logging.getLogger(__name__) # Creating a logger object with the name of the current module
handler = logging.config.dictConfig(**config['handlers']['file']) # Creating a handler object using the configuration for the 'file' handler
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') # Creating a formatter object to format the log messages
handler.setLevel(logging.DEBUG) # Setting the logging level for the handler to DEBUG
handler.setFormatter(formatter) # Setting the formatter for the handler
logger.addHandler(handler) # Adding the handler to the logger to handle the log messages

In this example, we’re loading our configuration from a YAML file and then setting up our logger and handler using the loaded settings. This is a great way to keep your logging code separate from your application logic if you prefer not to clutter it with too much setup.

With these tips, you’ll be able to format your messages like a pro and keep track of what’s happening in your code without having to sift through endless lines of output.

SICORPS