“Debugging is just problem-solving - attack it as such. Always try to discover the root cause of a problem, not just this particular appearance of it.” - Authors of Pragmatic Programmer

Debugging is a very important skill for any programmer. It is an essential part of the development process as it ensures that the software you are writing is reliable, efficient, and free of errors.

On the higher level it forces you to think about the code you are writing - seeing where errors occur, you gain a deeper understanding of the overall design and functionality of the code leading to better and more reliable design in the long run.

On the lower level you simply don’t waste as much time as it helps you identify issues as soon as possible.

Investing time into getting better at debugging saves you a lot of time in the long run.

As I’m writing a bit more challenging programs for my current skill-level I am permanently encountering bugs and errors.

That’s why I took some time and searched for how to get better at debugging topics.

Of course, it’s a whole set of tools that I still have yet to learn and understand, but one of them is logging. At the most basic level, it’s a simple print() statement.

But Python’s Standard Library offers a module that offers a lot more than just print() does. It’s called logging.

Python’s Logging module

Logging is a tool that provides flexible logging of messages. You can set a level of severity and handle each level separately.

Levels of debug you can set:

  • Debug - very detailed information
  • Info - confirms things are working
  • Warning - program runs, but something unexpected has happened
  • Error - some function failed
  • Critical - serious error, program may crash

There are many benefits to using Logging module. From clearly seeing where and when a logging call was made, customizing your logs, ability to log to pretty much anything, all at the same time, or as mentioned above, logging based on level of importance.

You can also manage logging for your whole project, set up which parts of your project should give you more logs, which less and so on to avoid confusion.

Example of setting up a very basic logger:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import logging

# create logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

# create console handler and set level to info
ch = logging.StreamHandler()

# Give us only messages of level INFO and higher
ch.setLevel(logging.INFO)

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# add formatter to console handler
ch.setFormatter(formatter)

# add console handler to logger
logger.addHandler(ch)

# 'application' code
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')

We import logging module, initialize logger object, set level to INFO (meaning we only receive messages of level INFO and higher), add console handler to handle messages in the console (we can set a FIleHandler in order to write messages into external file). We create formatter to style output messages as we prefer. Output looks as follows:

1
2
3
2023-05-01 11:31:00,622 - __main__ - INFO - This is an info message
2023-05-01 11:31:00,622 - __main__ - WARNING - This is a warning message
2023-05-01 11:31:00,622 - __main__ - ERROR - This is an error message

Another useful feature is also an option to set a level of logging in the command line by giving it as a parameter.

1
python app.py --log=debug

Just like with any other Python’s module, there is a lot more to learn and explore. This was just a very basic usage of Logging module that I recently learned.