How do I get the name of the class containing a logging call in Python?
If I want the function name I can simply include %(funcName)s
in the Formatter. But how do I get the name of the class conta开发者_开发百科ining the logging call instead?
I've gone through the documentation for logging
, but I can't find any mentioning of it.
For a rather easy, pythonic way to get the class name to output with your logger, simply use a 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 logger as above, the %(name)s
will be the name of your class
example output
$ 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(s)
Non-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()
You should use extra argument:
views.py
import logging
class SampleClass():
def sample_func(self):
logging.getLogger('info_logger').info('some text', extra={'className': self.__class__.__name__})
logger_settings.py
'format': '%(className)s | %(message)s ',
output log:
INFO | SampleClass | "some text"
There is almost certainly a better way of doing this, but until someone points that 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 output 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']
Yet another approach if you also want the module name:
class MyClass(object):
@property
def logger(self):
return logging.getLogger(f"{__name__}.{self.__class__.__name__}")
def what(self, ever):
self.logger.info("%r", ever)
I personally just tend to name my loggers after classes, as it makes it much easier to track down where a particular message came from. So you can have a root logger named "top", and for the module "a" and class "testclass", I name my logger "top.a.testclass".
I don't see the need to otherwise retrieve the classname, since the log message should give you all the information you need.
@ed's response above, it feels very unpythonic to me and it is not something I would be comfortable with using on production code.
This is a function to make an informative log message using the representation 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 to any class using a mix-in:
class UtilMixin(object):
def log(self, message: str = '') -> str:
""":returns: Log message formatting"""
return log_message(thing=self, message=message)
You can than be associated with a class using multiple inheritance:
class MyClass(object, UtilMixin):
def __repr__(self) -> str:
return '<{}>'.format(self)
pass
Usage
logger.warning(self.log('error message goes here'))
精彩评论