Debugging Made Easy: Using Logging to Monitor and Troubleshoot Your Python Code

Best Practices for Implementing Logging in Your Python Projects and Writing Cleaner, More Maintainable Code

Dipankar Medhi
3 min readJan 30, 2023

--

When building and maintaining software applications, debugging is an inevitable part of the development process. Even the most experienced developers can make mistakes or encounter unexpected issues during runtime. To help with troubleshooting, Python provides a built-in logging module that enables developers to easily record and output information about their code’s execution.

In this blog post, we will explore the basics of logging in Python, including why it’s important, how to set up a logger, and best practices for using it effectively. We will also provide code examples demonstrating how logging can be used to improve the quality and maintainability of your codebase.

Let us go through the necessary steps required to prepare the logging module.

Start by creating a logging_util.py file.

import logging

def get_logger(name, level):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)

console_handler = logging.StreamHandler()
file_handler = logging.FileHandler("file_log.log") # skip incase file saving not required

c_format = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
f_format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
console_handler.setFormatter(c_format)
file_handler.setFormatter(f_format)

logger.addHandler(console_handler)
logger.addHandler(file_handler)

return logger

The above code defines a function “get_logger ” that returns a logger object for logging messages.

The function takes two arguments: “name ”(the name of the logger) and “level” (the level of logging messages to be recorded).

The logging module is imported at the top of the code.

The logger is set to debug level and two handlers are created: console_handler and file_handler. Two different formatters are created for each handler to format the log messages in a specific way.

The console_handler will show the name, level name and message, while the file_handler will show the time, name, level name and message. Both handlers are added to the logger and the logger is returned.

The logger can be used to log messages at various levels, such as —

  • Debug
  • Info
  • Warning
  • Error
  • Critical

When a log message is sent to the logger, it will be passed to both handlers, and they will output the log message in their respective format to the console and a log file. In this case, the log file is named “file_log.log”.

Next, import the module into the application and log the required outputs.

from logging_util import get_logger

logger = get_logger(__name__)
logger.info("This is the log statement")

This code imports the “get_logger” function from the “logging_util” module.

A logger object is then created by calling the “get_logger” function and passing the argument “name”. This argument is a built-in Python variable that holds the name of the current module (in this case, the name of the module that this code is part of).

The “info” method of the logger object is then called to log a message with the log level “info”. This log statement will be handled by the handlers defined in the “get_logger” function of the “logging_util” module, which will output the log message to the console and/or a log file in a specific format.

That’s all folks!

Happy Coding 💛

--

--