如何将自定义loglevel添加到Python的日志记录工具中

2024-09-29 21:45:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我想对我的应用程序进行日志级跟踪(5),因为我认为debug()还不够。另外log(5, msg)不是我想要的。如何向Python记录器添加自定义日志级别?

我有一个mylogger.py包含以下内容:

import logging

@property
def log(obj):
    myLogger = logging.getLogger(obj.__class__.__name__)
    return myLogger

在我的代码中,我使用它的方式如下:

class ExampleClass(object):
    from mylogger import log

    def __init__(self):
        '''The constructor with the logger'''
        self.log.debug("Init runs")

现在我想打电话给self.log.trace("foo bar")

提前谢谢你的帮助。

编辑(2016年12月8日):我将接受的答案改为pfa's,即IMHO,这是一个基于Eric S非常好的建议的优秀解决方案


Tags: pydebugimportselflogobj应用程序logging
3条回答

结合所有现有的答案和大量的使用经验,我想我已经列出了所有需要做的事情,以确保完全无缝地使用新的级别。以下步骤假设您正在添加值为logging.DEBUG - 5 == 5的新级别TRACE

  1. logging.addLevelName(logging.DEBUG - 5, 'TRACE')需要调用才能在内部注册新级别,以便可以按名称引用它。
  2. 新的级别需要作为属性添加到logging本身以保持一致性:logging.TRACE = logging.DEBUG - 5
  3. 需要将名为trace的方法添加到logging模块中。它的行为应该像debuginfo
  4. 需要将名为trace的方法添加到当前配置的记录器类中。由于不能百分之百保证是logging.Logger,请改用logging.getLoggerClass()

以下方法说明了所有步骤:

def addLoggingLevel(levelName, levelNum, methodName=None):
    """
    Comprehensively adds a new logging level to the `logging` module and the
    currently configured logging class.

    `levelName` becomes an attribute of the `logging` module with the value
    `levelNum`. `methodName` becomes a convenience method for both `logging`
    itself and the class returned by `logging.getLoggerClass()` (usually just
    `logging.Logger`). If `methodName` is not specified, `levelName.lower()` is
    used.

    To avoid accidental clobberings of existing attributes, this method will
    raise an `AttributeError` if the level name is already an attribute of the
    `logging` module or if the method name is already present 

    Example
    -------
    >>> addLoggingLevel('TRACE', logging.DEBUG - 5)
    >>> logging.getLogger(__name__).setLevel("TRACE")
    >>> logging.getLogger(__name__).trace('that worked')
    >>> logging.trace('so did this')
    >>> logging.TRACE
    5

    """
    if not methodName:
        methodName = levelName.lower()

    if hasattr(logging, levelName):
       raise AttributeError('{} already defined in logging module'.format(levelName))
    if hasattr(logging, methodName):
       raise AttributeError('{} already defined in logging module'.format(methodName))
    if hasattr(logging.getLoggerClass(), methodName):
       raise AttributeError('{} already defined in logger class'.format(methodName))

    # This method was inspired by the answers to Stack Overflow post
    # http://stackoverflow.com/q/2183233/2988730, especially
    # http://stackoverflow.com/a/13638084/2988730
    def logForLevel(self, message, *args, **kwargs):
        if self.isEnabledFor(levelNum):
            self._log(levelNum, message, *args, **kwargs)
    def logToRoot(message, *args, **kwargs):
        logging.log(levelNum, message, *args, **kwargs)

    logging.addLevelName(levelNum, levelName)
    setattr(logging, levelName, levelNum)
    setattr(logging.getLoggerClass(), methodName, logForLevel)
    setattr(logging, methodName, logToRoot)

我接受了“避免看到lambda”的答案,并且不得不修改添加我的日志级别的日志的位置。我也看到了保罗所做的“我认为这不管用”的问题。您不需要logger作为日志级别的第一个参数吗?”这对我有效

import logging
DEBUG_LEVELV_NUM = 9 
logging.addLevelName(DEBUG_LEVELV_NUM, "DEBUGV")
def debugv(self, message, *args, **kws):
    # Yes, logger takes its '*args' as 'args'.
    self._log(DEBUG_LEVELV_NUM, message, args, **kws) 
logging.Logger.debugv = debugv

@埃里克S

Eric S.的回答很好,但我通过实验了解到,无论日志级别设置为什么,这都会导致在新的调试级别记录的消息被打印出来。因此,如果将9设为新的级别号,如果调用setLevel(50),则会错误地打印较低级别的消息。

To prevent that from happening, you need another line inside the "debugv" function to check if the logging level in question is actually enabled.

修复了检查日志记录级别是否已启用的示例:

import logging
DEBUG_LEVELV_NUM = 9 
logging.addLevelName(DEBUG_LEVELV_NUM, "DEBUGV")
def debugv(self, message, *args, **kws):
    if self.isEnabledFor(DEBUG_LEVELV_NUM):
        # Yes, logger takes its '*args' as 'args'.
        self._log(DEBUG_LEVELV_NUM, message, args, **kws) 
logging.Logger.debugv = debugv

如果您在Python 2.7的logging.__init__.py中查看class Logger的代码,这就是所有标准日志函数所做的工作(关键,.debug等)。

很明显我不能回复别人的回复,因为我的名声不好。。。如果埃里克看到这个,希望他能更新他的帖子。=)

相关问题 更多 >

    热门问题