How to get the name of a class containing a log call in Python?

If I need a function name, I can simply include %(funcName)s in the Formatter. But how do I get the name of the class containing the registration call?

I looked through the documentation for logging , but I can not find a mention of this.

+8
python class logging
source share
4 answers

For a fairly simple, pythonic way to get the class name for output with your registrar, simply use the logging class.

 import logging # Create a base class class LoggingHandler: def __init__(self, *args, **kwargs): self.log = logging.getLogger(self.__class__.__name__) # Create test class A that inherits the base class class testclassa(LoggingHandler): def testmethod1(self): # call self.log.<log level> instead of logging.log.<log level> self.log.error("error from test class A") # Create test class B that inherits the base class class testclassb(LoggingHandler): def testmethod2(self): # call self.log.<log level> instead of logging.log.<log level> self.log.error("error from test class B") testclassa().testmethod1() testclassb().testmethod2() 

By naming the registrar as indicated above, %(name)s will be the name of your class

Output example

 $ python mymodule.py [2016-02-03 07:12:25,624] ERROR [testclassa.testmethod1:29] error from test class A [2016-02-03 07:12:25,624] ERROR [testclassb.testmethod2:36] error from test class B 

Alternative Option (s)

For inheritance

 import logging def log(className): return logging.getLogger(className) class testclassa: def testmethod1(self): log(self.__class__.__name__).error("error from test class A") class testclassb: def testmethod2(self): log(self.__class__.__name__).error("error from test class B") testclassa().testmethod1() testclassb().testmethod2() 
+8
source share

There is almost certainly a better way to do this, but until someone points this out, this will work:

 import inspect class testclass: def testmethod(self): log() def log(): stack = inspect.stack() try: print "Whole stack is:" print "\n".join([str(x[4]) for x in stack]) print "-"*20 print "Caller was %s" %(str(stack[2][4])) finally: del stack testclass().testmethod() 

The result of this is the following:

 Whole stack is: [' stack = inspect.stack()\n'] [' f()\n'] ['testclass().testmethod()\n'] [' exec code in self.locals\n'] [' ret = method(*args, **kwargs)\n'] None -------------------- Caller was ['testclass().testmethod()\n'] 
+2
source share

I personally just call my registrars after class, as it makes it much easier to keep track of where a particular message came from. So you can have a root log named "top", and for module "a" and class "testclass" I call my log "top.a.testclass".

I do not see the need to otherwise retrieve the class name, since the log message should provide you with all the necessary information.

@ed answer above, it feels very hectic for me, and that is not what I would be comfortable using production code for.

0
source share

This is the function for creating a log informational message using the presentation class method:

https://docs.python.org/3/library/functions.html#repr

 def log_message(thing: object = None, message: str = '') -> str: """:returns: detailed error message using reflection""" return '{} {}'.format(repr(thing), message) 

This can be implemented in any class using mix-in:

 class UtilMixin(object): def log(self, message: str = '') -> str: """:returns: Log message formatting""" return log_message(thing=self, message=message) 

You can be associated with a class using multiple inheritance:

 class MyClass(object, UtilMixin): def __repr__(self) -> str: return '<{}>'.format(self) pass 

Using

 logger.warning(self.log('error message goes here')) 
0
source share

All Articles