Logging from static methods

Question:

In a class with few no static functions, I typically do logging like this:

class ClassA:

    def __init__(self):
        self._logger = logging.getLogger(self.__class__.__name__)

    def do_something(self):
        self._logger.info("Doing something")

    def do_something_else(self):
        self._logger.info("Doing something else.")

In a class with static methods I’ve been doing this:

class ClassB:

    _logger = logging.getLogger("ClassB")

    @staticmethod
    def do_something():
        ClassB._logger.info("Doing something")

    @staticmethod
    def do_something_else():
        ClassB._logger.info("Doing something else")

You could do this but it seems lame:

class ClassB:

    @staticmethod
    def do_something():
        logger = logging.getLogger("ClassB")
        logger.info("Doing something")

    @staticmethod
    def do_something_else():
        logger = logging.getLogger("ClassB")
        logger.info("Doing something else")

Is there a better pattern for logging from static methods?

Asked By: Matthew Lund

||

Answers:

You could turn them into class methods instead.

class ClassB(object):
    _logger = logging.getLogger("ClassB")

    @classmethod
    def do_something(cls):
         cls._logger.info("Doing something")

But note that when you derive from ClassB and call do_something, it will get a different logger since cls denotes the derived class rather than ClassB.

Answered By: Fred Foo

That pretty much does exhaust your options. After all, there are only three scopes accessible to a static method: the method scope, the class scope, and the module scope. And if you want to have the logger name match the class name, you will need at minimum one logger per class, so there’s no point in storing them at the module scope when you might as well store them at the class scope (as your second example does).

Personally, I usually use a logger per module. But if I were doing individual class loggers, I would probably use your pattern #2, having a _logger variable in each class. It just seems the cleanest to me.

Answered By: David Z

late to the answer party but would like to add one more point.

If you have a more complicated logger initialization (init file paths to log to, etc) then do you can do it by creating logger_init outside of the class.

def init_logger():
    logger = logging.getLogger('general_logger')
    # do other logger setup like
    # setup logger handlers,
    # set formatters,
    # set logging levels, etc
    return logger

then, init your logger from static class

 class MyClass(object):
     _logger = init_logger()

     @classmethod
     def do_something(cls):
         cls._logger.info("doing something")

happy logging!

Answered By: Denis Kanygin
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.