How to implement the --verbose or -v option in a script?

I know --verbose or -v for several tools, and I would like to implement this in some of my own scripts and tools.

I was thinking about placing:

 if verbose: print ... 

through my source code, so if the user -v option is -v , the verbose variable will be set to True and the text will be printed.

Is this the right approach or is there a more common way?

Addition: I am not asking for a way to implement argument parsing. This I know how to do it. I'm only interested in the detailed option.

+68
python option
May 12 '11 at 15:01
source share
9 answers

My suggestion is to use a function. But instead of putting if in a function that you could tempt, do this:

 if verbose: def verboseprint(*args): # Print each argument separately so caller doesn't need to # stuff everything to be printed into a single string for arg in args: print arg, print else: verboseprint = lambda *a: None # do-nothing function 

(Yes, you can define a function in an if , and it will be defined only if the condition is true!)

If you are using Python 3 where print already a function (or if you want to use print as a function in 2.x using from __future__ import print_function ), this is even simpler:

 verboseprint = print if verbose else lambda *a, **k: None 

Thus, a function is defined as do-nothing if verbose mode is turned off (using lambda) instead of constantly testing the verbose flag.

If the user could change the verbosity mode while starting your program, this would be the wrong approach (you will need if in the function), but since you set it using the command line flag, you only need to make a decision once.

Then you use, for example. verboseprint("look at all my verbosity!", object(), 3) whenever you want to print a "verbose" message.

+85
May 12 '11 at 15:09
source share

Use the logging module:

 import logging as log … args = p.parse_args() if args.verbose: log.basicConfig(format="%(levelname)s: %(message)s", level=log.DEBUG) log.info("Verbose output.") else: log.basicConfig(format="%(levelname)s: %(message)s") log.info("This should be verbose.") log.warning("This is a warning.") log.error("This is an error.") 

All of them will automatically go to stderr :

 % python myprogram.py WARNING: This is a warning. ERROR: This is an error. % python myprogram.py -v INFO: Verbose output. INFO: This should be verbose. WARNING: This is a warning. ERROR: This is an error. 

For more information, see Python Docs and tutorials .

+48
Mar 14 '13 at 15:04
source share

What I do in my scripts is to check at runtime if the "verbose" option is set, and then set the logging level for debugging. If it is not installed, I install it in the information. This way you don't have β€œif verbose” checks all your code.

+9
May 12 '11 at
source share

Building and simplifying @kindall's answer, this is what I usually use:

 v_print = None def main() parser = argparse.ArgumentParser() parser.add_argument('-v', '--verbosity', action="count", help="increase output verbosity (eg, -vv is more than -v)") args = parser.parse_args() if args.verbosity: def _v_print(*verb_args): if verb_args[0] > (3 - args.verbosity): print verb_args[1] else: _v_print = lambda *a: None # do-nothing function global v_print v_print = _v_print if __name__ == '__main__': main() 

In this case, you use the following script:

 v_print(1, "INFO message") v_print(2, "WARN message") v_print(3, "ERROR message") 

And your script can be called like this:

 % python verbose-tester.py -v ERROR message % python verbose=tester.py -vv WARN message ERROR message % python verbose-tester.py -vvv INFO message WARN message ERROR message 

A few notes:

  • Your first argument is your error level, and the second is your message. It has a magic number of 3 , which sets an upper bound on your logging, but I accept this as a compromise for simplicity.
  • If you want v_print work throughout your program, you need to make trash global. This is not fun, but I urge someone to find a better way.
+7
Feb 08 '13 at 0:07
source share

This could be vprint if you have a function called vprint that checks the verbose flag for you. Then you just call your own vprint function to any place where you need extra verbosity.

+2
May 12 '11 at 15:06
source share

I stole logging code from virtualenv for my project. Take a look at main() from virtualenv.py to see how it is initialized. The code is logger.notify() , logger.info() , logger.warn() , and the like. Which methods actually emit the output is determined by whether virtualenv was called using -v , -vv , -vvv or -q .

+2
Jun 07 '13 at 1:41
source share

I need a function that prints an object (obj), but only if the verbose global variable is true, otherwise it does nothing.

I want to be able to change the global verbose parameter at any time. Simplicity and readability are of utmost importance to me. Therefore, I would say that the following lines indicate:

 ak@HP2000:~$ python3 Python 3.4.3 (default, Oct 14 2015, 20:28:29) [GCC 4.8.4] on linux Type "help", "copyright", "credits" or "license" for more information. >>> verbose = True >>> def vprint(obj): ... if verbose: ... print(obj) ... return ... >>> vprint('Norm and I') Norm and I >>> verbose = False >>> vprint('I and Norm') >>> 

The global variable "verbose" can also be set from the parameter list.

0
Dec 29 '15 at 1:18
source share

@kindall's solution does not work with my version of Python 3.5. @styles correctly states in his comment that the reason is an optional optional keyword argument. So my slightly improved version for Python 3 looks like this:

 if VERBOSE: def verboseprint(*args, **kwargs): print(*args, **kwargs) else: verboseprint = lambda *a, **k: None # do-nothing function 
0
Sep 10 '16 at 13:47
source share

argparse there is a global variable, probably set using argparse from sys.argv , which sys.argv , should the program be verbose or not. Then the decorator could be written so that if verbosity were enabled, then standard input would be redirected to the null device while the function was to be executed:

 import os from contextlib import redirect_stdout verbose = False def louder(f): def loud_f(*args, **kwargs): if not verbose: with open(os.devnull, 'w') as void: with redirect_stdout(void): return f(*args, **kwargs) return f(*args, **kwargs) return loud_f @louder def foo(s): print(s*3) foo("bar") 

This answer is inspired by this code ; in fact, I was going to use it as a module in my program, but I had errors that I could not understand, so I adapted part of this.

The disadvantage of this solution is that verbosity is binary, unlike logging , which allows you to more precisely configure how verbose the program can be. In addition, all print calls are redirected, which may be undesirable for.

0
Jun 04 '18 at 7:49
source share



All Articles