Mastering Python Logging with a Singleton MyLog Class

This guide explains how to encapsulate a powerful, singleton-based logging system in Python using the MyLog class, covering OOP principles, code structure, and practical usage examples for flexible and maintainable log handling.

Ops Development & AI Practice
Ops Development & AI Practice
Ops Development & AI Practice
Mastering Python Logging with a Singleton MyLog Class

Effective logging is crucial in software development for debugging and maintenance. This article introduces a Python logging solution built around a custom MyLog class that leverages object‑oriented encapsulation and the Singleton pattern to provide a single, globally accessible logger.

What Is Encapsulation?

Encapsulation, one of the four core OOP principles, bundles data and the methods that operate on that data within a class, hiding internal implementation details and exposing only necessary interfaces. This improves code maintainability and reusability.

Design of the MyLog Class

The MyLog class implements a Singleton to ensure only one logger instance exists throughout the application lifecycle. The full class code is provided, defining constants for log path, name, format, and date format, and overriding __new__ to enforce the Singleton behavior.

import os
import logging
import sys

PATH = './logs'
NAME = 'default_log'
FMT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
DATEFMT = '%Y-%m-%d %H:%M:%S'

class MyLog(object):
    _instance = None

    def __new__(cls, *args, **kw):
        if cls._instance is None:
            MyLog._instance = object.__new__(cls)
        return MyLog._instance

    def __init__(self, config=None):
        if config:
            path = config.get('logpath')
            name = config.get('logname')
        else:
            path = PATH
            name = NAME
        if not os.path.exists(path):
            os.mkdir(path)
        self.logger = logging.getLogger()
        self.formatter = logging.Formatter(fmt=FMT, datefmt=DATEFMT)
        self.log_filename = '{0}/{1}.log'.format(path, name)
        self.logger.addHandler(self.get_file_handler(self.log_filename))
        self.logger.addHandler(self.get_console_handler())
        self.logger.setLevel(logging.DEBUG)

    @classmethod
    def get_instance(cls):
        return cls._instance

    def get_file_handler(self, filename):
        filehandler = logging.FileHandler(filename, encoding="utf-8")
        filehandler.setFormatter(self.formatter)
        return filehandler

    def get_console_handler(self):
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setFormatter(self.formatter)
        return console_handler

Singleton Implementation

The overridden __new__ method checks the class variable _instance. If it is None, a new instance is created and stored; otherwise, the existing instance is returned, guaranteeing a single logger object.

Constructor (__init__)

The constructor initializes the logger, allowing an optional configuration dictionary to specify custom log directory and filename. It creates the directory if missing, sets up a formatter, and attaches both file and console handlers.

Encapsulated Handler Creation

Two helper methods, get_file_handler and get_console_handler, encapsulate the creation of a file handler (with UTF‑8 encoding) and a console handler, respectively, each applying the shared formatter.

Usage Example

The following snippet demonstrates how to configure and use the MyLog class:

# Use MyLog class with custom log path and name
config = {
    'logpath': './my_log_directory',
    'logname': 'my_log_file'
}
logger = MyLog(config).logger

# Example log records
logger.debug("This is a debug message.")
logger.info("This is an info message.")
logger.warning("This is a warning message.")
logger.error("This is an error message.")
logger.critical("This is a critical message.")

This example creates a configuration dictionary, initializes MyLog, and logs messages at various severity levels.

Conclusion

By encapsulating logging logic within a Singleton class, developers gain a flexible, reusable, and easily configurable logging system. Mastering these OOP techniques leads to cleaner, more maintainable code in real‑world Python projects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonloggingOOPEncapsulationSingleton
Ops Development & AI Practice
Written by

Ops Development & AI Practice

DevSecOps engineer sharing experiences and insights on AI, Web3, and Claude code development. Aims to help solve technical challenges, improve development efficiency, and grow through community interaction. Feel free to comment and discuss.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.