如何在Python中获取包含日志记录调用的类的名称?

时间:2011-09-12 08:18:10

标签: python class logging

如果我想要功能名称,我只需在格式化程序中包含%(funcName)s即可。但是,如何获取包含日志记录调用的类的名称?

我已经阅读了logging的文档,但我找不到任何提及它。

4 个答案:

答案 0 :(得分:9)

要使用记录器输出类名的一种相当简单的pythonic方法,只需使用日志记录类。

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()

通过如上所述命名记录器,%(name)s将是您班级的名称

示例输出

$ 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

替代(S)

非继承

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()

答案 1 :(得分:2)

几乎可以肯定有一种更好的方法可以做到这一点,但在有人指出这一点之前,这会有效:

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()

输出结果如下:

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 :(得分:0)

我个人倾向于在课后命名我的记录器,因为它可以更容易地追踪特定消息的来源。所以你可以有一个名为“top”的根记录器,对于模块“a”和类“testclass”,我将我的记录器命名为“top.a.testclass”。

我认为不需要以其他方式检索类名,因为日志消息应该为您提供所需的所有信息。

@ ed上面的回复,对我来说感觉非常不合理,而且我不习惯使用生产代码。

答案 3 :(得分:0)

这是使用表示类方法生成信息性日志消息的函数:

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)

这可以使用混合实现到任何类:

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

您可以使用多重继承与类关联:

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

<强>用法

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