So I want to add logging to a little internal command line utility that I've been maintaining. (Actually I'm converting it's rather ugly manually coded logging to use Python's logging
module; and cleaning up some warts along the way).
First, I want to preserve the existing behavior, warts and all, for legacy usage. Any scripts which might be depending on the extraneous warnings that it already emits should not break as a result of what I'm doing. The new functionality should be through -v
switches, implemented in OptionParser as a type=count
(as per ancient Unix/Linux convention). The wrinkle here is that a single -v
sets the verbosity from -1 to 0 (zero) ... ironically squelching at least one warning message from the Paramiko libraries (No handlers could be
found for logger "paramiko.transport"). From there I want to support up to four additional -v
options and use those with logging.setLevel()
to be progressively more verbose, from logging.CRITICAL
only down to logging.DEBUG
.
There's the rub!
I can easily use something like:
if opts.verbosity == 0: # default is -1 do NOTHING
# 0 ironically makes it slightly quieter
logging.getLogger().addHandler(logging.NullHandler())
elif opts.verbosity > 0:
logging.basicConfig()
logging.getLogger().setLevel(50 - min(40, 10*opts.verbosity))
# UGLY BUT IT WORKS.
# logging.CRITICAL is 50,
# each -v reduces log filter by 10 down to 10
In other words I'm converting my count of -v
switches into a multiple of ten and subtracting that from the least verbose down towards the most verbose. (This is Python2.7.x by the way).
I've noticed that logging.basicConfig()
does away with the "No handles found" warning, and exposes some underlying error messages which have been (harmlessly) occurring for as long as this utility has been in production (years). (So, if I'd started with the default at 0, as one would expect, then I'd've introduced alarming noise to the users.
But my question is: is there a more "proper" way to translate from a numeric verbosity setting into a logging.setLevel()
? It seems dirty to use this implementation detail (the numeric values associated with logging.CRITICAL, logging.ERROR, logging.WARN,...
etc).
Surely I can't be the only one using -vvv
with Python's standard OptionParser
and logging
modules. But reading the docs and Googling around didn't find any sort of "best practices" on this.
Cleaner, at least:
level = {
1: logging.ERROR,
2: logging.WARNING,
3: logging.INFO,
4: logging.DEBUG
}.get(opts.verbosity, logging.DEBUG)
(I'd suggest converting from optparse
to argparse
too.)