I am trying to create a logging function with logging
in my main application that accepts 4 different values of verbosity with argparse
, default and -v
through to -vvv
. I have created a function (that has been minimised down for this) that outputs different information dependent upon the current value but I have no idea how to test for it. I pprinted
the logging.__dict__
but could not see where the current numeric value that was in effect in the programme was stored. Does anybody know how to get the current value so that I can test for it in if
blocks or if there is a better way for me to only call the appropriate def logging_print():
logging.log()
function?
The code has been referenced in-text with references to answers that have helped from this site:
import argparse
import logging
# https://stackoverflow.com/a/35804945/19520503
def addLoggingLevel(levelName, levelNum, methodName=None):
""""""
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)
def logging_print(msg, **kwargs):
""""""
#------ Some if conditions here depending on current logging value
logging.log(logging.VERBOSE, msg ' PRINTED')
logging.log(logging.INFO, msg)
logging.log(logging.DEBUG, msg)
return
def test_funct(text):
logging_print(test_funct.__name__)
return text
def main():
par = argparse.ArgumentParser()
par.add_argument('-v', '--verbose', action='count', default=0)
args = par.parse_args()
addLoggingLevel('VERBOSE', 15)
levels = [logging.WARNING, logging.INFO, logging.VERBOSE, logging.DEBUG]
level = levels[args.verbose]
logging.basicConfig(format=('%(asctime)s.%(msecs)d %(levelname)-8s '
'[%(filename)s: %(lineno)d] %(message)s'),
datefmt='%Y-%m-%d:%H:%M:%S',
level=level)
test_funct('test')
if __name__ == '__main__':
main()
I believe I understand why it is printing all three as it currently stands, the LoggingLevel
value when increased is triggering those in def logging_print()
that are less than the current value.
It is currently outputting:
scratch.py -v
2022-09-10:15:32:54.487 INFO [scratch.py: 38] test_funct
$ scratch.py -vv
2022-09-10:15:32:57.723 VERBOSE [scratch.py: 37] test_funct PRINTED
2022-09-10:15:32:57.724 INFO [scratch.py: 38] test_funct
$ scratch.py -vvv
2022-09-10:15:33:00.570 VERBOSE [scratch.py: 37] test_funct PRINTED
2022-09-10:15:33:00.571 INFO [scratch.py: 38] test_funct
2022-09-10:15:33:00.572 DEBUG [scratch.py: 39] test_func
How could this code be changed so it outputs like this please:
scratch.py -v
2022-09-10:15:32:54.487 INFO [scratch.py: 38] test_funct
$ scratch.py -vv
2022-09-10:15:32:57.723 VERBOSE [scratch.py: 37] test_funct PRINTED
$ scratch.py -vvv
2022-09-10:15:33:00.572 DEBUG [scratch.py: 39] test_func
I couldn't get the answers in How to get the current log level in python logging module to work with my question.
CodePudding user response:
You can use a custom logging handler to only print the current log level:
class OnlyCurrentLevelHandler(logging.StreamHandler):
def emit(self, record):
if record.levelno == self.level:
msg = self.format(record)
print(msg)
def main():
par = argparse.ArgumentParser()
par.add_argument('-v', '--verbose', action='count', default=0)
args = par.parse_args()
addLoggingLevel('VERBOSE', 15)
levels = [logging.WARNING, logging.INFO, logging.VERBOSE, logging.DEBUG]
level = levels[args.verbose]
handler = OnlyCurrentLevelHandler()
handler.setLevel(level)
logging.basicConfig(format=('%(asctime)s.%(msecs)d %(levelname)-8s '
'[%(filename)s: %(lineno)d] %(message)s'),
datefmt='%Y-%m-%d:%H:%M:%S',
level=level,
handlers=[handler]
)
test_funct('test')