更简单的方法来启用详细日志记录

use*_*146 58 python python-2.7

我想添加一个调试print语句测试,如果我--verbose从命令行启用,如果我在脚本中有以下内容.

logger.info("test")
Run Code Online (Sandbox Code Playgroud)

我经历了以下问题,但无法得到答案......

Mat*_*ang 104

我发现--verbose(对于用户而言)和--debug(对于开发人员)都很有用.以下是我如何使用loggingargparse:

import argparse
import logging

parser = argparse.ArgumentParser()
parser.add_argument(
    '-d', '--debug',
    help="Print lots of debugging statements",
    action="store_const", dest="loglevel", const=logging.DEBUG,
    default=logging.WARNING,
)
parser.add_argument(
    '-v', '--verbose',
    help="Be verbose",
    action="store_const", dest="loglevel", const=logging.INFO,
)
args = parser.parse_args()    
logging.basicConfig(level=args.loglevel)
Run Code Online (Sandbox Code Playgroud)

因此,如果--debug设置,则将日志记录级别设置为DEBUG.如果--verbose,日志记录设置为INFO.如果两者都没有,缺少--debug将日志记录级别设置为默认值WARNING.

  • 我真的很喜欢这种方法......让argparse做所有的工作,没有`if`s或者parse_args之后的任何东西 (7认同)
  • @MestreLion:谢谢。对我来说确实很蟒蛇。 (2认同)
  • @MatthewLeingang:要做到这一点,你必须使用几个[处理程序](https://docs.python.org/2/howto/logging.html#handlers).以下是示例:http://stackoverflow.com/a/16066513/1088577 (2认同)
  • @MatthewLeingang 当输出是控制台/终端时,通常最好将所有消息发送到 stderr。将它们发送到 stdout 通常会使您的程序在 UNIX 管道中使用变得更加困难。我的经验法则是 stdout -> 程序输出,stderr -> 程序消息。 (2认同)

Joh*_*web 71

您需要将Argparse教程的智慧与Python的Logging HOWTO结合起来.这是一个例子......

> cat verbose.py 
#!/usr/bin/env python

import argparse
import logging

parser = argparse.ArgumentParser(
    description='A test script for http://stackoverflow.com/q/14097061/78845'
)
parser.add_argument("-v", "--verbose", help="increase output verbosity",
                    action="store_true")

args = parser.parse_args()
if args.verbose:
    logging.basicConfig(level=logging.DEBUG)

logging.debug('Only shown in debug mode')
Run Code Online (Sandbox Code Playgroud)

运行帮助:

> ./verbose.py -h
usage: verbose.py [-h] [-v]

A test script for http://stackoverflow.com/q/14097061/78845

optional arguments:
  -h, --help     show this help message and exit
  -v, --verbose  increase output verbosity
Run Code Online (Sandbox Code Playgroud)

以详细模式运行:

> ./verbose.py -v
DEBUG:root:Only shown in debug mode
Run Code Online (Sandbox Code Playgroud)

默默地运行:

> ./verbose.py   
> 
Run Code Online (Sandbox Code Playgroud)


Sti*_*ley 47

这是一个更简洁的方法,它执行边界检查,并将在帮助中列出有效值:

parser = argparse.ArgumentParser(description='This is a demo.')
parser.add_argument("-l", "--log", dest="logLevel", choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], help="Set the logging level")

args = parser.parse_args()
if args.logLevel:
    logging.basicConfig(level=getattr(logging, args.logLevel))
Run Code Online (Sandbox Code Playgroud)

用法:

demo.py --log DEBUG
Run Code Online (Sandbox Code Playgroud)

  • 不需要`getattr`:`level = logging.getLevelName(args.logLevel)` (12认同)
  • 更好的是将`default ='INFO'`添加到`add_argument()`以及`(默认:%(默认)s)`到帮助文本,然后删除`if args.logLevel`并始终调用` basicConfig()`.然后,用户可以知道默认值将始终是什么. (9认同)

ece*_*ulm 22

另一种变体是计算数量-v并使用计数作为a的索引list,其实际级别来自logging:

import argparse
import logging

parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbose', action='count', default=0)
args = parser.parse_args()

levels = [logging.WARNING, logging.INFO, logging.DEBUG]
level = levels[min(len(levels)-1,args.verbose)]  # capped to number of levels

logging.basicConfig(level=level,
                    format="%(asctime)s %(levelname)s %(message)s")

logging.debug("a debug message")
logging.info("a info message")
logging.warning("a warning message")
Run Code Online (Sandbox Code Playgroud)

这适用于-vvvv,-vvv,-vv,-v,-v -v,等,如果没有-vlogging.WARNING选择更多,如果-v提供的话,将会给INFODEBUG

  • 太好了!只需记住将脚本作为`python script.py -v [other_args]`运行.如果你在脚本之前运行`python -v script.py`(`-v`),你将从Python解释器本身获得大量的调试输出,但不会从你的脚本中获得.(答案不是问题,只是对其他读者的警告). (4认同)

Ste*_*han 8

您可以明确指定一个级别作为-v标志后的整数:

parser = argparse.ArgumentParser()
parser.add_argument("-v", "--verbose", const=1, default=0, type=int, nargs="?",
                    help="increase verbosity: 0 = only warnings, 1 = info, 2 = debug. No number means info. Default is no verbosity.")
args = parser.parse_args()

logger = logging.getLogger()
if args.verbose == 0:
    logger.setLevel(logging.WARN) 
elif args.verbose == 1:
    logger.setLevel(logging.INFO) 
elif args.verbose == 2:
    logger.setLevel(logging.DEBUG) 
Run Code Online (Sandbox Code Playgroud)