I write CLI-executable Python 3 scripts regularly to do data compilation and some maintenance tasks, and try to adhere to PEP 8 and the Google Python Style Guide when doing so. Google's guide says to avoid using global variables, while PEP 8 offers naming conventions but doesn't really encourage or discourage use of them, so I don't use them.
However, I've lately found myself using a "verbose" option/switch a lot along with a "printv
" function to use while debugging. It usually looks like this:
def printv(opts, msg, **kwargs):
if opts.verbose: print(msg, **kwargs)
As incredibly lazy as I am, I'd like to make it so I don't need to pass the opts
argument (which is an OptionParser
object) to printv
. The simplest method would be to use a global variable, sure. Another thought I had would be to set a "VERBOSE" variable in os.environ
, since the switch is, conceptually, making a change to the execution environment. Obviously it's counter-intuitive, but is it pythonic?
2 Answers 2
IMHO the level of visibility where you grab your options from should typically match the level of visibility of your printv
function. So when there is just one global printv
function visible everywhere in your program, it is ok to have the "verbose option" also visible globally. If your printv
is instead a class member (for example, of a "Logger" class, see comment from DXM), the "verbose option" should be a member of the same class. If it is a function within a module - same rule. This feels somewhat natural to me, however I hardly believe that this is a python specific idiom.
Using an environment variable is appropriate for controlling the "verbose option" from outside the program, this makes no sense if the "verbose state" is only switched on and off inside your program. If you need this (for example, because you have two or more programs which shall be controlled by the same VERBOSE environment variable), read the environment once after the program start and store the state in your internal globalOpts.verbose
variable (for later usage, for example, in your printv
function).
Storing program state in the environment is not Pythonic.
Looking at the GPSG section on Global Variables it says explicitly that one of the exceptions includes default options for scripts; I would say if your CLI is a single file script, then having your opts
object be global is just fine.
logging
module and I can't believe I hadn't noticed it before. Just what the doctor ordered, and I'm loving how it can be configured, especially in how it can output to both the terminal and a file in one call, with each destination able to have its own independent settings for format and level.