What's an easy way to implement a --quiet option in a python script
Am working on a command line python script - throughout the script, I have a lot of information I am print
-ing to the terminal window so that I may follow along with what is happening.
Using OptionParser
I want to add a --quiet
option so I can silence all the output. I am looking for a pythonic way to go about implementing this throughout the script so that I don't end up doing something like:
if not QUIET: # global variable set by OptionParser
print " my output 开发者_如何学编程"
Am new to python and sure there is a better way. Ideas?
You could use logging
and assign those things that should not be printed if QUIET
a different log level.
Edit: THC4K's answer shows an example of how to do this, assuming that all output should be silent if QUIET
is set. Note that in Python 3 from __future__ import print_function
is not necessary:
print = logging.info
logging.basicConfig(level=logging.WARNING if QUIET else logging.INFO,
format="%(message)s")
For for important output that should not be silenced by --quiet
, define e.g. iprint
:
iprint = logging.warning
can silence all the output by running it as python myscript.py > /dev/null
change the output streams in the script:
if QUIET:
sys.stdout = open(os.devnull, 'a')
sys.stderr = open(os.devnull, 'a')
print(something)
use a different print function
from __future__ import print_function
if QUIET:
def print(*args):
pass
print(something)
use logging and loglevels
from __future__ import print_function
import logging
logging.basicConfig(level=logging.INFO, format="%(message)s")
print = logging.info
if QUIET:
logging.basicConfig(level=logging.ERROR)
print(something)
Why don't you just modify your output function based on whether the program is in quiet mode, so you only do the check once?
if QUIET:
def DoOutput(stuff):
pass
else:
def DoOutput(stuff):
print(stuff)
Or, you could of course put the check for QUIET
inside your output function:
def DoOutput(stuff):
if QUIET:
print(stuff)
The situation that you've described is actually one of the reasons that Python 3 has changed print
from a keyword to an actual function: people's large projects were becoming very dependent on print
being a keyword, and then when it came time to modify how output was recorded, it required a massive refactoring; whereas when print
is a proper function, you can just redefine it, so that print(foo)
would output to a log file, for instance. That's why it's better practice to wrap your output/logging in an actual function, rather than having print
scattered about your script.
You could replace stdout with a proxy that filters calls to write or writelines:
class FileProxy(object):
def __init__(self, real_file, quiet_flag):
self.real_file = real_file
self.quiet_flag = quiet_flag
def write(self, string):
if not self.quiet_flag:
self.real_file.write(string)
def writelines(self, strings):
if not self.quiet_flag:
self.real_file.write(strings)
def __getattr__(self, name):
return getattr(self.file, name)
import sys
sys.stdout = FileProxy(sys.stdout, QUIET)
The advantage of this is that it is cross platform (unlike writing to /dev/null) and it will still work for print statements in third-party libraries that you do not have control over. You could also refine it further to give more control over exactly what is written, e.g. to add a timestamp, or redirect print statements to the logging system.
If you want it quick and dirty and you want to get rid of all output then redirect stdout and stderr to /dev/null. Put:
sys.stdout = open("/dev/null", "a") sys.stderr = open("/dev/null", "a")
At the point where you detect --quiet.
if QUIET:
sys.stdout=open("/dev/null","w")
...
print 'my output'
On Windows, use "nul" instead of "/dev/null"
精彩评论