我无法使用python的标准logging
正确记录我的模块。然而,这是一个非常简单的案例。
我有以下模块层次结构:
module\
foo.py
bar.py
我需要使用以下约束来记录每个模块:
INFO
到控制台的所有日志> = module.foo
(因为此模块的功能很重要,用户必须现场通知)module.*
到文件的所有日志WARNING
从module.*
到控制台这是主要代码
import logging
import logging.config
import os
import yaml
def setup_logging():
loadfrom = os.path.join(os.path.dirname(__file__), 'config.yml')
# Load
with open(loadfrom, 'rt') as f:
config = yaml.safe_load(f.read())
logging.config.dictConfig(config)
setup_logging()
foo = logging.getLogger('module.foo')
bar = logging.getLogger('module.bar')
foo.info('module.foo doing something')
foo.debug('module.foo debug data')
bar.info('module.bar doing something')
bar.error('module.bar something bad happened')
以下是我使用
的配置version: 1
disable_existing_loggers: False
formatters:
simple:
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
handlers:
console:
class: logging.StreamHandler
level: INFO
formatter: simple
stream: ext://sys.stdout
file:
class: logging.handlers.RotatingFileHandler
level: DEBUG
filename: 'log.log'
formatter: simple
encoding: utf8
loggers:
module:
level: WARNING
handlers: [console]
propagate: yes
module.foo:
level: INFO
handlers: [console]
propagate: yes # If yes, gets displayed twice. If false, entry is missing in log file
root:
level: DEBUG
handlers: [file]
这是输出:
2017-09-21 10:48:39,679 - module.foo - INFO - module.foo doing something
2017-09-21 10:48:39,679 - module.foo - INFO - module.foo doing something
2017-09-21 10:48:39,681 - module.bar - ERROR - module.bar something bad happened
子模块中的log.info
显示两次,因为配置中propagate
字段设置为yes。
将其设置为false可解决控制台中的问题但会中断日志文件,因为其中缺少该条目。
我该如何解决这个问题?标准库的任何替代品,我个人认为违反直觉?
@ wmorell回答后的新配置:
handlers:
console:
class: logging.StreamHandler
level: INFO
formatter: simple
stream: ext://sys.stdout
file:
class: logging.handlers.RotatingFileHandler
level: DEBUG
filename: 'log.log'
formatter: simple
encoding: utf8
loggers:
module:
level: WARNING
handlers: [console]
propagate: yes
module.foo:
level: DEBUG <- set this to debug
handlers: [file, console] <- Add file here
propagate: false
root:
level: DEBUG
handlers: [file]
控制台输出正常:
2017-09-21 11:14:51,174 - module.foo - INFO - module.foo doing something
2017-09-21 11:14:51,174 - module.bar - ERROR - module.bar something bad happened
日志输出不正常,错过了对log.info('module.bar')
的调用:
2017-09-21 11:18:34,335 - module.foo - INFO - module.foo doing something
2017-09-21 11:18:34,335 - module.foo - DEBUG - module.foo debug data
2017-09-21 11:18:34,335 - module.bar - ERROR - module.bar something bad happened
答案 0 :(得分:1)
将file
处理程序显式添加到记录器定义,然后复制console
处理程序以过滤掉不同的日志级别:
handlers:
console_info:
class: logging.StreamHandler
level: INFO
formatter: simple
stream: ext://sys.stdout
console_warning:
class: logging.StreamHandler
level: WARNING
formatter: simple
stream: ext://sys.stdout
file:
class: logging.handlers.RotatingFileHandler
level: DEBUG
filename: 'log.log'
formatter: simple
encoding: utf8
loggers:
module:
level: DEBUG
handlers: [file, console_warning]
propagate: false
module.foo:
level: DEBUG
handlers: [file, console_info]
propagate: false
首先在记录器定义中对日志进行过滤,因此module
和module.foo
记录器必须允许DEBUG
,如果要将其记录到日志文件中。记录器然后将消息转发给所有处理程序,处理程序可以将消息丢弃到其配置的阈值以下;因此,您需要一个处理程序,它将删除基本INFO
记录器的module
日志,以及一个允许INFO
日志记录更具体的module.foo
记录器的处理程序。