简体   繁体   English

Python:如何从OptionParser type ='count'记录logging.setLevel详细程度?

[英]Python: How to logging.setLevel verbosity from OptionParser type='count'?

So I want to add logging to a little internal command line utility that I've been maintaining. 因此,我想将日志记录添加到一个我一直维护的内部命令行实用程序中。 (Actually I'm converting it's rather ugly manually coded logging to use Python's logging module; and cleaning up some warts along the way). (实际上,我正在将其转换为使用Python的logging模块的丑陋的手动编码日志logging ,并在此过程中清除了一些疣)。

First, I want to preserve the existing behavior, warts and all, for legacy usage. 首先,我想保留现有行为,疣和所有行为,以供传统使用。 Any scripts which might be depending on the extraneous warnings that it already emits should not break as a result of what I'm doing. 任何可能依赖于它已经发出的无关警告的脚本都不应由于我正在执行的操作而中断。 The new functionality should be through -v switches, implemented in OptionParser as a type=count (as per ancient Unix/Linux convention). 新功能应通过-v开关实现,该选项在OptionParser中作为type=count (根据古老的Unix / Linux约定)。 The wrinkle here is that a single -v sets the verbosity from -1 to 0 (zero) ... ironically squelching at least one warning message from the Paramiko libraries (No handlers could be found for logger "paramiko.transport"). 这里的难题是,单个-v将详细程度从-1设置为0(零)...具有讽刺意味的是,它压缩了Paramiko库中的至少一个警告消息(找不到记录程序“ paramiko.transport”的处理程序)。 From there I want to support up to four additional -v options and use those with logging.setLevel() to be progressively more verbose, from logging.CRITICAL only down to logging.DEBUG . 从那里开始,我要支持多达四个附加的-v选项,并将它们与logging.setLevel()一起使用,使其变得越来越冗长,从logging.CRITICAL一直到logging.DEBUG

There's the rub! 有摩擦!

I can easily use something like: 我可以轻松地使用类似:

if opts.verbosity == 0: # default is -1 do NOTHING
    # 0 ironically makes it slightly quieter
    logging.getLogger().addHandler(logging.NullHandler())
elif opts.verbosity > 0:
    logging.basicConfig()
    logging.getLogger().setLevel(50 - min(40, 10*opts.verbosity))
    # UGLY BUT IT WORKS.
    # logging.CRITICAL is 50, 
    # each -v reduces log filter by 10 down to 10

In other words I'm converting my count of -v switches into a multiple of ten and subtracting that from the least verbose down towards the most verbose. 换句话说,我正在将-v开关的计数转换为十的倍数,并将其从最小的详细信息向下减去最详细的信息。 (This is Python2.7.x by the way). (顺便说一下,这是Python2.7.x)。

I've noticed that logging.basicConfig() does away with the "No handles found" warning, and exposes some underlying error messages which have been (harmlessly) occurring for as long as this utility has been in production (years). 我注意到logging.basicConfig()消除了“找不到句柄”警告,并暴露了一些基本的错误消息,只要该实用程序已经投入生产(几年),这些错误消息就一直(无害)发生。 (So, if I'd started with the default at 0, as one would expect, then I'd've introduced alarming noise to the users. (因此,如果像人们期望的那样从默认值0开始,那么我会给用户带来令人震惊的噪音。

But my question is: is there a more "proper" way to translate from a numeric verbosity setting into a logging.setLevel() ? 但是我的问题是:是否存在从数字详细设置转换为logging.setLevel() “适当”方法? It seems dirty to use this implementation detail (the numeric values associated with logging.CRITICAL, logging.ERROR, logging.WARN,... etc). 使用此实现细节(与logging.CRITICAL, logging.ERROR, logging.WARN,...等相关的数值)似乎很脏。

Surely I can't be the only one using -vvv with Python's standard OptionParser and logging modules. 当然,不能将-vvv与Python的标准OptionParserlogging模块一起使用。 But reading the docs and Googling around didn't find any sort of "best practices" on this. 但是,阅读文档并进行谷歌搜索并没有发现任何“最佳实践”。

Cleaner, at least: 更清洁,至少:

level = {
    1: logging.ERROR,
    2: logging.WARNING,
    3: logging.INFO,
    4: logging.DEBUG
}.get(opts.verbosity, logging.DEBUG)

(I'd suggest converting from optparse to argparse too.) (我建议也从optparse转换为argparse 。)

(yay reviving old posts) (是的,恢复旧帖子)

I've recently wanted something like this as well but I didn't want to use a dict . 我最近也想要这样的东西,但是我不想使用dict Here's my implementation: 这是我的实现:

def logging_level(verbosity):
    """ Converts a verbosity number to a logging level

    Args:
        verbosity - a number, possibly collected from ``argparse``'s ``count``
        action. If ``verbosity`` is out of the range of possible logging levels
        it will be normalized to the nearest level. Does not take into
        consideration custom levels.
    """
    levels = [
        logging.CRITICAL,
        logging.ERROR,
        logging.WARNING,
        logging.INFO,
        logging.DEBUG
    ]

    return levels[max(min(len(levels) - 1, verbosity), 0)]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM