Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Python logger has no attribute 'info', 'debug'

I have a class that I use to have a single logger across my project.

import os
from logging import DEBUG, FileHandler, Formatter, Logger, StreamHandler, getLogger
from typing import Set


class SingleLogger:
    __logger: Logger = None  # type: ignore
    __handler: StreamHandler = None  # type: ignore
    __logging_files: Set[str] = set()

    @classmethod
    def __create_and_configure_logger(cls) -> None:
        if cls.__logger is not None:
            return

        logger = getLogger("shared_logger")
        logger.level = DEBUG

        stream_handler = StreamHandler()
        stream_handler.level = DEBUG
        stream_handler.formatter = Formatter(
            "%(asctime)s %(name)s %(levelname)s: %(message)s"
        )
        __handler = stream_handler
        logger.addHandler(__handler)

        cls.__logger = logger

    @classmethod
    def add_filehandler_to_shared_logger(
        cls, file: str = "/tmp/gipcheslogs.txt", for_notebook: bool = False
    ) -> None:
        if file in cls.__logging_files:
            return

        try:
            if not os.path.exists(file):
                with open(file=file, mode="w", encoding="utf-8") as log_file:
                    log_file.write("")
                    log_file.close()
        except IOError:
            return

        cls.__logging_files.add(file)
        file_handler = FileHandler(file)
        file_handler.level = DEBUG
        file_handler.formatter = Formatter(
            "%(asctime)s %(name)s %(levelname)s: %(message)s"
        )

        cls.shared_logger.addHandler(file_handler)

        if for_notebook:
            cls.__logger.removeHandler(cls.__handler)

    @classmethod
    @property
    def shared_logger(cls) -> Logger:
        """
        Returns:
            Logger: the shared singleton logger, and create it if necessary.
        """
        if not cls.__logger:
            cls.__create_and_configure_logger()

        return cls.__logger


SingleLogger.shared_logger.info(msg="Hello")
SingleLogger.shared_logger.debug(msg="Hello")

The code above runs with no problems on Python3.9 or above, but when I run the same code on Python3.8 or lower, I immediately get the following error:

AttributeError: 'property' object has no attribute 'info'

I’m not sure what is the difference between the two version of Python and why that affects the Logger.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Removing the @property from the shared_logger method and calling it using SingleLogger.shared_logger().info("Hi") fixes the issue, but once again, I don’t know why.

>Solution :

You’re wrapping a property with @classmethod. That was functionality added in 3.9… and removed in 3.11, because it turned out to be a bad idea that broke too much stuff.

Since it was added in 3.9, it will of course not work if you run your code on 3.8. Since it was removed in 3.11, you should stop using that functionality anyway.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading