python中的记录器链

时间:2010-06-07 12:24:52

标签: python logging

我正在编写python包/模块,并希望日志消息提到它们来自哪个模块/类/函数。即如果我运行此代码:

import mymodule.utils.worker as worker

w = worker.Worker()
w.run()

我想记录消息如下:

2010-06-07 15:15:29 INFO mymodule.utils.worker.Worker.run <pid/threadid>: Hello from worker

我该如何做到这一点?

感谢。

2 个答案:

答案 0 :(得分:8)

我倾向于在我的包/模块中使用日志记录模块,如下所示:

import logging
log = logging.getLogger(__name__)
log.info("Whatever your info message.")

这会将记录器的名称设置为模块的名称以包含在日志消息中。您可以在格式字符串中找到%(name)s的位置,控制名称的位置。同样,您可以将pid放置%(process)d,将线程ID放置%(thread)d。所有选项均为See the docs

格式化示例:

import logging
logging.basicConfig(format="%(asctime)s %(levelname)s %(name)s %(process)d/%(threadName)s: %(message)s")
logging.getLogger('this.is.the.module').warning('Testing for SO')

给我:

2010-06-07 08:43:10,494 WARNING this.is.the.module 14980/MainThread: Testing for SO

答案 1 :(得分:2)

以下是我在讨论中提出的解决方案。感谢大家的建议。

用法:

>>> import logging
>>> logging.basicConfig(level=logging.DEBUG)
>>> from hierlogger import hierlogger as logger
>>> def main():
...     logger().debug("test")
...
>>> main()
DEBUG:main:test

默认情况下,它会将记录器命名为...您还可以通过提供参数来控制深度:
3 - module.class.method默认
2 - module.class
1 - 仅模块

还会缓存记录器实例,以防止在每次调用时计算记录器名称。 我希望有人会喜欢它。

代码:

import logging
import inspect

class NullHandler(logging.Handler):
        def emit(self, record): pass

def hierlogger(level=3):
    callerFrame = inspect.stack()[1]
    caller = callerFrame[0]
    lname = '__heirlogger'+str(level)+'__'
    if lname not in caller.f_locals:
        loggerName = str()
        if level >= 1:
            try:
                loggerName += inspect.getmodule(inspect.stack()[1][0]).__name__
            except: pass
        if 'self' in caller.f_locals and (level >= 2):
            loggerName += ('.' if len(loggerName) > 0 else '') + 
                          caller.f_locals['self'].__class__.__name__
        if callerFrame[3] != '' and level >= 3:
            loggerName += ('.' if len(loggerName) > 0 else '') + callerFrame[3]
        caller.f_locals[lname] = logging.getLogger(loggerName)
        caller.f_locals[lname].addHandler(NullHandler())
    return caller.f_locals[lname]