我知道--verbose
或-v
来自几种工具,我想在自己的一些脚本和工具中实现这一点。
我想到放置:
if verbose:
print ...
通过我的源代码,以便如果用户通过该-v
选项,则变量verbose
将设置为,True
并且将打印文本。
这是正确的方法还是有更常见的方法?
另外:我并没有要求实现参数解析的方法。我知道怎么做。我只对详细选项特别感兴趣。
我知道--verbose
或-v
来自几种工具,我想在自己的一些脚本和工具中实现这一点。
我想到放置:
if verbose:
print ...
通过我的源代码,以便如果用户通过该-v
选项,则变量verbose
将设置为,True
并且将打印文本。
这是正确的方法还是有更常见的方法?
另外:我并没有要求实现参数解析的方法。我知道怎么做。我只对详细选项特别感兴趣。
Answers:
我的建议是使用一个函数。但是不要像if
可能会尝试将in 放入函数那样,而是这样做:
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
(是的,您可以在if
语句中定义一个函数,只有在条件为true时才会被定义!)
如果您使用的是Python 3,则其中print
已经是一个函数(或者如果您愿意使用print
,在2.x中用作函数from __future__ import print_function
),它甚至更简单:
verboseprint = print if verbose else lambda *a, **k: None
这样,如果关闭了详细模式(使用lambda),则该函数被定义为“不执行任何操作”,而不是不断测试该verbose
标志。
如果用户可以在程序运行期间更改详细模式,则这是错误的方法(您需要if
在函数中使用),但是由于您是使用命令行标志设置的,因此您只需要一次做决定。
然后,您可以verboseprint("look at all my verbosity!", object(), 3)
在每次要打印“详细”消息时使用例如。
print
函数:接受许多参数。它可以print(*args)
在3.x和for arg in args: print arg,
2.x中实现。主要优点是它允许在一条消息中混合字符串和其他类型的内容,而无需显式str
调用/格式化和串联。
print arg,
行末尾的逗号是什么?
def verboseprint(*args, **kwargs): print(*args, **kwargs)
使用logging
模块:
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.")
所有这些都自动转到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.
有关更多信息,请参见Python Docs和教程。
构建和简化@kindall的答案,这是我通常使用的方法:
v_print = None
def main()
parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbosity', action="count",
help="increase output verbosity (e.g., -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()
然后,在整个脚本中提供了以下用法:
v_print(1, "INFO message")
v_print(2, "WARN message")
v_print(3, "ERROR message")
您的脚本可以这样调用:
% 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
几个注意事项:
3
可为您的日志记录设置上限,但我接受这是为简便起见而做出的折衷。v_print
在整个程序中工作,则必须与全局对象打交道。这没什么好玩的,但是我向某人挑战以寻求更好的方法。-v
。在您当前的解决方案中,所有内容都将转储到stdout而不是stderr。并且:您通常希望将每个错误传递给用户,不是吗?
@kindall的解决方案不适用于我的Python 3.5版。@styles在他的注释中正确指出,原因是附加的可选关键字参数。因此,我对Python 3略加精炼的版本如下所示:
if VERBOSE:
def verboseprint(*args, **kwargs):
print(*args, **kwargs)
else:
verboseprint = lambda *a, **k: None # do-nothing function
可能存在一个可能由argparse
from 设置的全局变量,sys.argv
它表示程序是否应该冗长。然后可以编写一个装饰器,使得如果启用了冗长性,那么只要函数运行,标准输入就将被转移到空设备中:
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")
这个答案受此代码的启发; 实际上,我只是将其用作程序中的一个模块,但遇到了无法理解的错误,因此我对它进行了部分修改。
该解决方案的缺点是,冗长性是二进制的,与之不同的是logging
,它允许对程序的冗长程度进行微调。同样,所有 print
呼叫都被转移,这可能是不必要的。
我需要的是一个打印对象(obj)的函数,但是仅当全局变量verbose为true时,否则它什么都不做。
我希望能够随时更改全局参数“详细”。对我而言,简单性和可读性至关重要。因此,我将按照以下几行内容进行操作:
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')
>>>
也可以从参数列表中设置全局变量“ verbose”。