设置日志记录级别

Posted

技术标签:

【中文标题】设置日志记录级别【英文标题】:Set logging levels 【发布时间】:2016-11-27 00:48:43 【问题描述】:

我正在尝试使用标准库来调试我的代码:

这很好用:

import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
logger.info('message')

我无法让较低级别的记录器工作:

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.info('message')

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.debug('message')

我没有得到任何回应。

【问题讨论】:

【参考方案1】:

什么 Python 版本?这在 3.4 中对我有用。但请注意,basicConfig() 不会影响已设置的根处理程序:

如果根记录器已经为其配置了处理程序,则此函数不执行任何操作。

要在 root 上显式设置级别,请执行 logging.getLogger().setLevel(logging.DEBUG)。但请确保您事先已调用basicConfig(),以便根记录器最初进行一些设置。即:

import logging
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
logging.getLogger('foo').debug('bah')
logging.getLogger().setLevel(logging.INFO)
logging.getLogger('foo').debug('bah')

还请注意,“记录器”和它们的“处理程序”都具有不同的独立日志级别。因此,如果您之前在 Python 脚本中显式加载了一些复杂的记录器配置,并且与根记录器的处理程序混淆,那么这可能会产生影响,并且仅使用 logging.getLogger().setLevel(..) 更改记录器日志级别可能不会工作。这是因为附加的处理程序可能具有独立设置的日志级别。这种情况不太可能发生,您通常不必担心。

【讨论】:

您现在可以向 basicConfig 发送 force=True 以使其工作,即使它已经设置好了。【参考方案2】:

我使用以下设置进行日志记录

基于 Yaml 的配置

像这样创建一个名为 logging.yml 的 yaml 文件

version: 1

formatters:
    simple:
        format: "%(name)s - %(lineno)d -  %(message)s"

    complex:
        format: "%(asctime)s - %(name)s - %(lineno)d -  %(message)s"


handlers:
    console:
        class: logging.StreamHandler
        level: DEBUG
        formatter: simple

    file:
        class: logging.handlers.TimedRotatingFileHandler
        when: midnight
        backupCount: 5
        level: DEBUG
        formatter: simple
        filename : Thrift.log

loggers:

    qsoWidget:
        level: INFO
        handlers: [console,file]
        propagate: yes

    __main__:   
        level: DEBUG
        handlers: [console]
        propagate: yes

Python - 主要

“主”模块应如下所示

import logging.config
import logging

with open('logging.yaml','rt') as f:
        config=yaml.safe_load(f.read())
        f.close()
logging.config.dictConfig(config)
logger=logging.getLogger(__name__)
logger.info("Contest is starting")

子模块/类

这些应该像这样开始

import logging

class locator(object):
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.logger.debug(' initialized')

希望对你有帮助...

【讨论】:

qsoWidget 只是您应用的名称吗? __init__.py 中包含所有日志配置不是最佳做法吗?这是一个问题。 我会说 - 您应该尝试将日志记录设置放在项目中可能的最高点。然后让依赖的模块使用它。这样你就有了一致的日志记录。对每个模块执行模块将导致不同级别、不同的日志格式输出。这将使下游日志处理(Humio、Splunk、PIG)变得更加困难。 很好的例子!谢谢你。通过 .yaml 设置记录器配置听起来是一个非常有效的解决方案 @AlexSkorokhod 我认为 yaml 是可读的,但是将日志记录在外部文件中,可以让您在不接触代码的情况下改变日志级别。【参考方案3】:

在我看来,这是大多数情况下的最佳方法。

通过 INI 文件配置

在项目根目录下创建文件名logging.ini,如下:

[loggers]
keys=root

[logger_root]
level=DEBUG
handlers=screen,file

[formatters]
keys=simple,verbose

[formatter_simple]
format=%(asctime)s [%(levelname)s] %(name)s: %(message)s

[formatter_verbose]
format=[%(asctime)s] %(levelname)s [%(filename)s %(name)s %(funcName)s (%(lineno)d)]: %(message)s

[handlers]
keys=file,screen

[handler_file]
class=handlers.TimedRotatingFileHandler
interval=midnight
backupCount=5
formatter=verbose
level=WARNING
args=('debug.log',)

[handler_screen]
class=StreamHandler
formatter=simple
level=DEBUG
args=(sys.stdout,)

然后配置如下:

import logging

from logging.config import fileConfig

fileConfig('logging.ini')
logger = logging.getLogger('dev')


name = "***"

logger.info(f"Hello name!")
logger.critical('This message should go to the log file.')
logger.error('So should this.')
logger.warning('And this, too.')
logger.debug('Bye!')

如果您运行脚本,sysout 将是:

2021-01-31 03:40:10,241 [INFO] dev: Hello ***!
2021-01-31 03:40:10,242 [CRITICAL] dev: This message should go to the log file.
2021-01-31 03:40:10,243 [ERROR] dev: So should this.
2021-01-31 03:40:10,243 [WARNING] dev: And this, too.
2021-01-31 03:40:10,243 [DEBUG] dev: Bye!

debug.log 文件应包含:

[2021-01-31 03:40:10,242] CRITICAL [my_loger.py dev <module> (12)]: This message should go to the log file.
[2021-01-31 03:40:10,243] ERROR [my_loger.py dev <module> (13)]: So should this.
[2021-01-31 03:40:10,243] WARNING [my_loger.py dev <module> (14)]: And this, too.

全部完成。

【讨论】:

【参考方案4】:

我想将默认记录器保留在警告级别,但我的代码有详细的低级记录器。但它不会显示任何东西。在另一个答案的基础上,事先运行logging.basicConfig() 至关重要。

import logging
logging.basicConfig()
logging.getLogger('foo').setLevel(logging.INFO)
logging.getLogger('foo').info('info')
logging.getLogger('foo').debug('info')
logging.getLogger('foo').setLevel(logging.DEBUG)
logging.getLogger('foo').info('info')
logging.getLogger('foo').debug('debug')

预期输出

INFO:foo:info
INFO:foo:info
DEBUG:foo:debug

对于跨模块的日志记录解决方案,我这样做了

# cfg.py

import logging
logging.basicConfig()
logger = logging.getLogger('foo')
logger.setLevel(logging.INFO)
logger.info(f'active')

# main.py

import cfg
cfg.logger.info(f'main')

【讨论】:

以上是关于设置日志记录级别的主要内容,如果未能解决你的问题,请参考以下文章

设置日志记录级别

Spring Boot:如何使用 application.properties 设置日志记录级别?

如何在 Tomcat 中将级别日志记录设置为 DEBUG?

通过环境变量设置 Quarkus 日志记录类别级别

C++日志记录类以及日志记录程序

是否可以在 GLib 新结构化日志记录中为每个域/日志级别设置不同的写入器函数?