DEV Community

Lameck Odhiambo
Lameck Odhiambo

Posted on Edited on

Python Logging

The Python logging module is the standard library facility used to track events, monitor application health, and debug problems instead of using print() statements. It provides features like log levels, custom formatting, and destinations like the console or log files.

Log Levels

  • Python categorizes log logs by severity. By default, the system ignores logs below the WARNING level.
  • When no log level is defined, the default log level is set to warning, so anything below warning (that is DEBUG, INFO) won't work.

Basic Configuration

import logging

logging.basicConfig(filename='sample.log',level= logging.INFO, 
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

def add(x,y):
    return x + y

def subtract (x,y):
    return x - y 

logging.info(add(23,7))

logging.info(subtract(23,7))
Enter fullscreen mode Exit fullscreen mode

Output

2026-11-06 15:06:04,927 - root - INFO - 30
2026-11-06 15:06:04,928 - root - INFO - 16
Enter fullscreen mode Exit fullscreen mode
  • The output of the logs are stored in sample.log file. This is where you can track events and debug problems.
  • Format enables you to define how the logs will be written.
  • The sample code above cannot use DEBUG level, because its below INFO. Otherwise WARNING, ERROR, CRITICAL can be used.

Production level configuration

  • __name__ enables us to specify different loggings for different files even when imported, it still maintains and uses the defined configurations within the file.
import logging

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

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler = logging.FileHandler('class.log')
file_handler.setFormatter(formatter)

logger.addHandler(file_handler)


# logging.basicConfig(filename='class.log',level= logging.INFO, 
#                     format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')


class Employee:
    def __init__(self, emp_name, emp_dept):
        self.emp_name = emp_name
        self.emp_dept = emp_dept

    def info(self):
        logger.info(f"{self.emp_name} works in {self.emp_dept} department")

emp1 = Employee("Lameck", "Data")
emp1.info()
Enter fullscreen mode Exit fullscreen mode

Output:

2026-11-06 15:29:48,602 - __main__ - INFO - Lameck works in Data department
Enter fullscreen mode Exit fullscreen mode

Log Streaming

  • If you want to see the logs in the console and not in a specific file then we use streamHandler()
# Create a logger named after the current module
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

# Create a console handler
console_handler = logging.StreamHandler()

# Define format 
formatter = logging.Formatter('%(levelname)s: %(message)s')
console_handler.setFormatter(formatter)

# Add handler to the logger
logger.addHandler(console_handler)

def calculate_total(price = 3900, tax= 23):
    logger.info("Starting total calculation...")
    return price + (price * tax)

logger.info(calculate_total())
Enter fullscreen mode Exit fullscreen mode

Output:

PS C:\Users\DELL\Documents\logging> python stream.py
INFO: Starting total calculation...
INFO: 93600
Enter fullscreen mode Exit fullscreen mode

Handling Errors using Logging

  • To log errors effectively in Python, we use the logger.exception() method inside an except block. This automatically captures the full exception traceback alongside your custom message, which is essential for debugging.
import logging

logger = logging.getLogger(__name__)

try:
    result = 10 / 0
except ZeroDivisionError:
    # Automatically captures the complete stack trace at ERROR level
    logger.exception("An error occurred while dividing numbers")
Enter fullscreen mode Exit fullscreen mode

Conclusion

Python’s built-in logging module is the industry-standard tool for tracking application behavior, diagnosing bugs, and replacing brittle print() statements in production code. By utilizing hierarchical loggers, structured severity levels, and isolated handlers, it provides a flexible framework that scales easily from tiny scripts to massive microservices.

Top comments (0)