我希望我的应用程序有loglevel TRACE (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,这是一个基于Eric S的非常好的提案的优秀解决方案。
发布于 2012-11-30 10:17:06
@Eric S.
Eric S.的答案非常好,但我通过实验了解到,这总是会导致打印记录在新调试级别的消息--无论日志级别设置为什么。因此,如果您设置了一个新的9
级别编号,如果您调用setLevel(50)
,则将错误地打印较低级别的消息。
为了防止这种情况发生,您需要在"debugv“函数中使用另一行代码来检查所讨论的日志记录级别是否真的已启用。
修复检查日志级别是否开启的示例:
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看到这篇文章,希望他会更新他的帖子。=)
发布于 2016-03-05 03:54:20
结合所有现有的答案和大量的使用经验,我想我已经列出了所有需要做的事情,以确保新级别的完全无缝使用。以下步骤假定您正在添加值为logging.DEBUG - 5 == 5
的新level TRACE
需要调用
logging.addLevelName(logging.DEBUG - 5, 'TRACE')
来获得在内部注册的新级别,以便可以通过名称引用它。为了保持一致性,需要将新级别作为属性添加到logging
本身:需要将名为trace
的logging.TRACE = logging.DEBUG - 5
.logging
模块中。它的行为应该与debug
、info
等类似。trace
的方法添加到当前配置的记录器类中。由于这不能100%保证为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)
发布于 2012-08-03 04:08:52
我接受了的回答,并不得不修改添加log_at_my_log_level
的位置。我也看到了Paul所做的问题--我不认为这是可行的。你不需要logger作为log_at_my_log_level
__的第一个参数吗?这对我很有效
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
https://stackoverflow.com/questions/2183233
复制相似问题