Are you struggling with logging messages that look like they were written by a robot?
In case you didn’t know, Python has added two new formatting approaches since version 2.4: string.Template and str.format(). Logging (as of 3.2) now provides better support for these two additional formatting styles as well. The Formatter class has been enhanced to take an optional keyword parameter named style that defaults to ‘%’, but other possible values are ‘{‘ and ‘$’ which correspond to the other two formatting styles.
Let me show you how this works in action! First, let’s create a simple console session:
# Import the logging module
import logging
# Set the root logger to the DEBUG level
root = logging.getLogger()
root.setLevel(logging.DEBUG)
# Create a StreamHandler to handle the logging output
handler = logging.StreamHandler()
# Create a Formatter object with a custom format and style
bf = logging.Formatter('{asctime} {name} {levelname:8s} {message}', style='{')
# Set the Formatter object as the format for the StreamHandler
handler.setFormatter(bf)
# Add the StreamHandler to the root logger
root.addHandler(handler)
# Create a logger object for the current module
logger = logging.getLogger(__name__)
# The above code sets up the logging configuration, including the format and style of the log messages.
# The root logger is set to the DEBUG level, which means all messages with a level of DEBUG or higher will be logged.
# A StreamHandler is created to handle the logging output, and a custom Formatter object is created with a specific format and style.
# The Formatter object is then set as the format for the StreamHandler, and the StreamHandler is added to the root logger.
# Finally, a logger object is created for the current module, which will be used to log messages specific to this module.
In this example, we’re setting up a logger with the default level of DEBUG and adding a StreamHandler to it. We then create a Formatter object that uses string interpolation (style='{‘) for our log messages. This will allow us to use {}- or $-formatting in place of %(message)s or {message} respectively.
Now let’s test this out by logging some data:
# Import the logging module
import logging
# Create a logger object with the name 'my_logger'
my_logger = logging.getLogger('my_logger')
# Set the default level of the logger to DEBUG
my_logger.setLevel(logging.DEBUG)
# Create a StreamHandler object and add it to the logger
stream_handler = logging.StreamHandler()
my_logger.addHandler(stream_handler)
# Create a Formatter object that uses string interpolation for log messages
formatter = logging.Formatter(style='{')
# Set the formatter for the StreamHandler
stream_handler.setFormatter(formatter)
# Log some data at different levels
my_logger.debug('This is a debug message!') # Logs a debug message
my_logger.info('This is an info message!') # Logs an info message
my_logger.warning('This is a warning message!') # Logs a warning message
my_logger.error('This is an error message!') # Logs an error message
my_logger.critical('This is a critical message!') # Logs a critical message
When you run this code, you’ll see something like this in your console:
# This script is used to log different types of messages in a module called "my_module.py"
# Import the necessary module for logging
import logging
# Set the format for the log messages
logging.basicConfig(format='%(asctime)s %(module)s %(levelname)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
# Create a logger object for the module
logger = logging.getLogger(__name__)
# Set the logging level to DEBUG
logger.setLevel(logging.DEBUG)
# Log a debug message
logger.debug('This is a debug message!')
# Log an info message
logger.info('This is an info message!')
# Log a warning message
logger.warning('This is a warning message!')
# Log an error message
logger.error('This is an error message!')
# Log a critical message
logger.critical('This is a critical message!')
As you can see, the log messages now use string interpolation instead of the old format strings. You’ll also notice that we used __name__ to get the name of our module for better context in the logs.