2

I found similar questions here, but my question is bit different... I have log() function as staticmethod in MyUtil class:

class MyUtil(object):

    @staticmethod
    def log(message, level):
    ...

but now I have to know from which class/object this staticmethod was called? For example:

class Deployer(object):

    def deploy(self):
        ...
        MyUtil.log ("Starting deployment", "info")
        ...

Is it possible to get and log this "Deployer" class name from MyUtil.log function?

(I'm aware that this is very un-OO and probably never useful in a well written program, but anyway...)

deniszh
  • 774
  • 1
  • 5
  • 14
  • You can pass `classname` as parameter.. – Rohit Jain Sep 28 '12 at 10:08
  • 1
    It would be handy to include references to similar questions you've found. This'll help people know what isn't the answer you're after, and will help people in the future as they may find this question, and the answer they're after is one of your similar ones :) – Jon Clements Sep 28 '12 at 10:15
  • @JonClements, thanks, there was couple of similar questions when I post mine, but when I try to edit question - there is no more. Will do it next time. :) – deniszh Sep 28 '12 at 11:21

3 Answers3

3

Have you consider writing a logging module like implementation. Something like following

Make a seperate Logger class. When you need a logger object call Logger.get_logger(your_class_name). This method either create a new logger and return it back or return already created Logger for that particular logger name. Then use this logger.

That way you can change your own logger with standard logger any time you need. And developers will be familiar with the methods you are using.

logger = Logger.get_logger(Deployer.__class__.__name__)
logger.info("Starting deployment")

Here is a very simple logger implementation.

"""
Sample logger implementation
"""
import datetime


class Logger:
    """
    Main logger class
    """
    _cached_loggers = dict()

    def __init__(self, logger_name):
        self.name = logger_name
        self._cached_loggers[logger_name] = self

    @classmethod
    def get_logger(cls, logger_name):
        """
        Return a new logger or already existed one
        """
        if logger_name in cls._cached_loggers:
            logger = cls._cached_loggers[logger_name]
        else:
            logger = Logger(logger_name)
        return logger

    def info(self, msg):
        """
        logging info logs
        """
        print u"{0} - {1} - {2}".format(self.name,
                                        datetime.datetime.now(),
                                        unicode(msg))
yilmazhuseyin
  • 6,442
  • 4
  • 34
  • 38
  • could you -please- add a small Logger example-class? – Thomas Schwärzl Sep 28 '12 at 10:53
  • Thanks, it's way better solution, but it requires some amount of refactoring work. Will think about it. – deniszh Sep 28 '12 at 11:19
  • @deniszh Another solution would be to just use standard logging module. And change your logging handler according to your needs. Here is some standard logging handlers one of them might suit your needs http://docs.python.org/library/logging.handlers.html. If they don't, You can just write one logging handler your-self as explained in this question http://stackoverflow.com/questions/3118059/how-to-write-custom-python-logging-handler. – yilmazhuseyin Sep 28 '12 at 11:30
1

It's not the nicest design, logging is a "singleton" with all of its drawbacks, but if you are willing to accept that, there's some language support for your problem. You can get the caller by inspecting the stack:

import inspect

class MyUtil(object):
    @staticmethod
    def log(message, level):
        frame, module, line, function, context, index = inspect.stack()[1]
        self_name = frame.f_code.co_varnames[0]  # Name of the first argument (usually 'self')
        instance = frame.f_locals[self_name]
        class_name = instance.__class__.__name__
        print class_name

class Deployer(object):
    def deploy(self):
        MyUtil.log ("Starting deployment", "info")

Deployer().deploy()
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • Thank you, it was that I realy want to do, but as I found I need to sometimes go deep down in stack for right class name... Maybe it will better to rewrite logging, but anyway :) – deniszh Sep 28 '12 at 11:17
0

As you know that everything in Python is Object.. So, you can actually pass the Class Object as a parameter to your method..

So, you can change your method definition like this: -

class MyUtil(object):

    @staticmethod
    def log(message, level, ClassName):

And pass the object of calling class into this method: -

class Deployer(object):

    def deploy(self):
        ...
        MyUtil.log ("Starting deployment", "info", Deployer)
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525