Skip to content

Instantly share code, notes, and snippets.

@huklee
Last active January 6, 2024 18:06
Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save huklee/cea20761dd05da7c39120084f52fcc7c to your computer and use it in GitHub Desktop.
Save huklee/cea20761dd05da7c39120084f52fcc7c to your computer and use it in GitHub Desktop.
python Logger using example with Singleton Pattern
# -*- coding: utf-8 -*-
import logging
import os
import datetime
import time
class SingletonType(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(SingletonType, cls).__call__(*args, **kwargs)
return cls._instances[cls]
# python 3 style
class MyLogger(object, metaclass=SingletonType):
# __metaclass__ = SingletonType # python 2 Style
_logger = None
def __init__(self):
self._logger = logging.getLogger("crumbs")
self._logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s \t [%(levelname)s | %(filename)s:%(lineno)s] > %(message)s')
now = datetime.datetime.now()
dirname = "./log"
if not os.path.isdir(dirname):
os.mkdir(dirname)
fileHandler = logging.FileHandler(dirname + "/log_" + now.strftime("%Y-%m-%d")+".log")
streamHandler = logging.StreamHandler()
fileHandler.setFormatter(formatter)
streamHandler.setFormatter(formatter)
self._logger.addHandler(fileHandler)
self._logger.addHandler(streamHandler)
print("Generate new instance")
def get_logger(self):
return self._logger
# a simple usecase
if __name__ == "__main__":
logger = MyLogger.__call__().get_logger()
logger.info("Hello, Logger")
logger.debug("bug occured")
@aK0nshin
Copy link

'time' imported but unused

@witt3rd
Copy link

witt3rd commented Nov 28, 2021

Thanks for example! I simplified it a bit using __new__:

import logging
import os
import datetime


class MyLogger:
    _logger = None

    def __new__(cls, *args, **kwargs):
        if cls._logger is None:

            print("Logger new")
            cls._logger = super().__new__(cls, *args, **kwargs)
            cls._logger = logging.getLogger("crumbs")
            cls._logger.setLevel(logging.DEBUG)
            formatter = logging.Formatter(
                '%(asctime)s \t [%(levelname)s | %(filename)s:%(lineno)s] > %(message)s')

            now = datetime.datetime.now()
            dirname = "./log"

            if not os.path.isdir(dirname):
                os.mkdir(dirname)
            fileHandler = logging.FileHandler(
                dirname + "/log_" + now.strftime("%Y-%m-%d")+".log")

            streamHandler = logging.StreamHandler()

            fileHandler.setFormatter(formatter)
            streamHandler.setFormatter(formatter)

            cls._logger.addHandler(fileHandler)
            cls._logger.addHandler(streamHandler)

        return cls._logger


# a simple usecase
if __name__ == "__main__":
    logger = MyLogger()
    logger.info("Hello, Logger")
    logger = MyLogger()
    logger.debug("bug occured")

@oijkn
Copy link

oijkn commented Jan 28, 2022

Thank you for sharing, exactly what I need 👍

@Santunav
Copy link

Excellent , working perfect and the formatting done well

@flavienbwk
Copy link

You should probably better use a metaclass.

@khlkh
Copy link

khlkh commented Dec 11, 2022

Why there are two assignments to the same variable? Isn't that the second one will overwrite the first?
cls._logger = super().new(cls, *args, **kwargs)
cls._logger = logging.getLogger("crumbs")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment