Setting log level based on --quiet, --debug flags

My application writes a lot of log messages at different levels, mainly INFO and DEBUG. Some of these may be printed to stdout, depending on the command line flags --quiet and --debug.

  • If --quiet is passed, ERROR-level messages and above should be printed.
  • If --debug is passed, DEBUG-level messages and above should be printed.
  • If neither flag is passed, INFO-level and above should be printed.
  • If both --quiet and --debug are passed, --debug takes precedence.

I’m currently setting the log level like this:

logger.setLevel(
    min(
        (
            logging.ERROR,
            logging.INFO + quiet * logging.ERROR,
            logging.DEBUG + (not debug) * logging.ERROR,
        ),
    )
)

which works, but isn’t very clear IMO. What is a nicer way to print the desired messages based on the above criteria?

if debug:
    logger.setLevel('DEBUG')
elif quiet:
    logger.setLevel('ERROR')
else:
    logger.setLevel('INFO')

This is:

  • easier to read
  • easier to maintain
  • runs faster
  • takes fewer lines
3 Likes

I often use something like this:

p = ArgumentParser(…)

g = p.add_mutually_exclusive_group()
g.add_argument(
  "--quiet", 
  action="store_const", 
  dest="log_level", 
  const=logging.ERROR
)
g.add_argument(
  "--debug", 
  action="store_const", 
  dest="log_level", 
  const=logging.DEBUG
)

p.set_default(log_level=logging.INFO)

Elsewhere:

options = p.parse_args(…)
# setting up a logger:
logger.setLevel(options.log_level)

Of course you can use whatever option names you like and add help text to the options. I don’t worry about debug taking precedence over quiet, because if a user sets both they get my argparse help text. :wink:

2 Likes

Personally I like options to accumulate left to right, because that way
a user can amend a command line’s behaviour by appending additional
(possibly overriding) options. Particularly handy if the base CLI
incantation is buried inside another script.

2 Likes

That’s a very good point! I hadn’t considered that before. I’ll have to think about that next time I’m argparsing.

Edit: I think for my example removing the mutually exclusive group may achieve this? I haven’t tried it yet but if the options have the same dest a later one should overwrite the earlier one.