首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何向Python的日志记录工具添加自定义日志级别

如何向Python的日志记录工具添加自定义日志级别
EN

Stack Overflow用户
提问于 2010-02-02 18:16:04
回答 16查看 65.5K关注 0票数 147

我希望我的应用程序有loglevel TRACE (5),因为我不认为debug()是足够的。另外,log(5, msg)不是我想要的。如何向Python日志记录器添加自定义日志级别?

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

代码语言:javascript
复制
import logging

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

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

代码语言:javascript
复制
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,这是一个基于Eric S的非常好的提案的优秀解决方案。

EN

回答 16

Stack Overflow用户

回答已采纳

发布于 2012-11-30 10:17:06

@Eric S.

Eric S.的答案非常好,但我通过实验了解到,这总是会导致打印记录在新调试级别的消息--无论日志级别设置为什么。因此,如果您设置了一个新的9级别编号,如果您调用setLevel(50),则将错误地打印较低级别的消息。

为了防止这种情况发生,您需要在"debugv“函数中使用另一行代码来检查所讨论的日志记录级别是否真的已启用。

修复检查日志级别是否开启的示例:

代码语言:javascript
复制
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

如果您查看Python2.7的logging.__init__.py中的class Logger代码,这就是所有标准日志函数(.critical、.debug等)所做的事情。

显然,我不能回复别人的答案,因为缺乏声誉...如果Eric看到这篇文章,希望他会更新他的帖子。=)

票数 204
EN

Stack Overflow用户

发布于 2016-03-05 03:54:20

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

需要调用

  1. logging.addLevelName(logging.DEBUG - 5, 'TRACE')来获得在内部注册的新级别,以便可以通过名称引用它。为了保持一致性,需要将新级别作为属性添加到logging本身:需要将名为tracelogging.TRACE = logging.DEBUG - 5.
  2. A方法添加到logging模块中。它的行为应该与debuginfo等类似。
  3. 需要将名为trace的方法添加到当前配置的记录器类中。由于这不能100%保证为logging.Logger,因此请改用logging.getLoggerClass()

所有步骤如下图所示:

代码语言:javascript
复制
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)
票数 79
EN

Stack Overflow用户

发布于 2012-08-03 04:08:52

我接受了的回答,并不得不修改添加log_at_my_log_level的位置。我也看到了Paul所做的问题--我不认为这是可行的。你不需要logger作为log_at_my_log_level__的第一个参数吗?这对我很有效

代码语言:javascript
复制
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
票数 67
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2183233

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档