Combinando todas las respuestas existentes con un montón de experiencia de uso, creo que he elaborado una lista de todas las cosas que se deben hacer para garantizar un uso completamente fluido del nuevo nivel. Los pasos a continuación asumen que está agregando un nuevo nivel TRACE
con valor logging.DEBUG - 5 == 5
:
logging.addLevelName(logging.DEBUG - 5, 'TRACE')
debe invocarse para que el nuevo nivel se registre internamente para que se pueda hacer referencia a él por su nombre.
- El nuevo nivel necesita ser añadido como un atributo a
logging
sí mismo para mantener la coherencia: logging.TRACE = logging.DEBUG - 5
.
- Es
trace
necesario agregar un método llamado al logging
módulo. Se debe comportarse igual debug
, info
, etc.
- Es
trace
necesario agregar un método llamado a la clase de registrador configurada actualmente. Dado que esto no está 100% garantizado logging.Logger
, utilícelo logging.getLoggerClass()
en su lugar.
Todos los pasos se ilustran en el método siguiente:
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)