Get current logging value to output different verbosity levels

Question:

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.

Asked By: 1ae1_NADPH

||

Answers:

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')
Answered By: Tom McLean
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.