Python记录器/处理程序配置错误?

时间:2020-05-28 07:53:31

标签: python logging configuration ipython handler

尽管我已经使用python / ipython已有一段时间了,但我认为自己还是一个新手。我想我从文档中了解了很多事情,特别是关于日志记录支持,但是显然比以前希望的要困难得多。我正在将ipython 5.5.0 / python 2.7.17 on Xubuntu 18.04.04 LTS与色标一起使用。我的日志记录配置模块如下。

import coloredlogs
import datetime
import logging
import logging.config
import os
import yaml

def setup_logging( default_path='../Config/logging.yaml',
                   default_level=logging.DEBUG,
                   env_key='LOG_CFG'):

  path = os.path.join(os.path.dirname(os.path.realpath(__file__)), default_path)
  value = os.getenv(env_key, None)

  # If the envvar is set, use it's value
  if value:
    path = value

  _dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  print("%s Using Logging Configuration: %s" % (_dt, path) )

  #
  # If the configuration file path is there, read it
  #
  if os.path.exists(path):
    with open(path, 'rt') as f:
      try:
        config = yaml.safe_load(f.read())
        logging.config.dictConfig(config)
        coloredlogs.install(level=default_level)
      except Exception as err:
        print(err)
        print('Error in Logging Configuration. Using default configs')
        logging.basicConfig(level=default_level)
        coloredlogs.install(level=default_level)

  # Otherwise, continue without a configuration
  else:
    logging.basicConfig(level=logging.DEBUG)
    coloredlogs.install(level=logging.DEBUG)
    print('Failed to load configuration file. Using default configs')

该配置保存在具有以下定义的yaml文件中。

version: 1
disable_existing_loggers: False

formatters:
    basic:
        format: "%(name)s - %(message)s"
    standard:
        format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    error:
        format: "%(levelname)s <PID %(process)d:%(processName)s> %(name)s.%(funcName)s(): %(message)s"

handlers:
    console_basic:
        class: logging.StreamHandler
        level: DEBUG
        formatter: basic
        stream: ext://sys.stdout

    console_out:
        class: logging.StreamHandler
        level: DEBUG
        formatter: standard
        stream: ext://sys.stdout

    console_err:
        class: logging.StreamHandler
        level: DEBUG
        formatter: standard
        stream: ext://sys.stderr

    debug_file_handler:
        class: logging.handlers.RotatingFileHandler
        level: DEBUG
        formatter: standard
        filename: /tmp/debug.log
        maxBytes: 10485760 # 10MB
        backupCount: 20
        encoding: utf8

    info_file_handler:
        class: logging.handlers.RotatingFileHandler
        level: INFO
        formatter: standard
        filename: /tmp/info.log
        maxBytes: 10485760 # 10MB
        backupCount: 20
        encoding: utf8

    warn_file_handler:
        class: logging.handlers.RotatingFileHandler
        level: WARN
        formatter: standard
        filename: /tmp/warn.log
        maxBytes: 10485760 # 10MB
        backupCount: 20
        encoding: utf8

    error_file_handler:
        class: logging.handlers.RotatingFileHandler
        level: ERROR
        formatter: error
        filename: /tmp/errors.log
        maxBytes: 10485760 # 10MB
        backupCount: 20
        encoding: utf8

    critical_file_handler:
        class: logging.handlers.RotatingFileHandler
        level: CRITICAL
        formatter: standard
        filename: /tmp/critical.log
        maxBytes: 10485760 # 10MB
        backupCount: 20
        encoding: utf8

root:
    level: CRITICAL
    handlers: [console_err]
    propogate: no

loggers:
  test:
    level: DEBUG
    handlers: [console_basic]
    propogate: no

  Utils.paragraph_processing:
    level: DEBUG
    handlers: [info_file_handler, debug_file_handler, warn_file_handler, error_file_handler, critical_file_handler]
    propogate: no

  Utils.graphing_functions:
    level: DEBUG
    handlers: [info_file_handler, debug_file_handler, warn_file_handler, error_file_handler, critical_file_handler]
    propogate: no

下面是我的test.py模块的以下代码段。

import coloredlogs
from copy import deepcopy
import cv2
import imutils
import logging
import logging.config
import os
import yaml

import matplotlib.pyplot as PLT
import matplotlib.image as MPI
import numpy as np

import Tests.filtering_tests as FT
import Tests.morphology_tests as MT

import Utils.global_defs as GL
import Utils.graphing_functions as GF
import Utils.paragraph_processing as PP
import Utils.logging_functions as LF

.
.
.
def phony_main():
  LF.setup_logging()
  # create logger
  LOG = logging.getLogger(__name__)

  LOG.critical("Logging Started...")


# -----------------------------------------------------------------------------
#
# Main
#
img = None

if __name__ == "__main__":
    # execute only if run as a script
    phony_main()

我的问题是,当我将配置从[console_out]更改为[console_basic]时,我希望消息符合要求,但它们并不一致。使我相信其他一些记录程序root(?)正在处理该呼叫吗?但是,如果我更改为使用[console_basic],则消息仍然相同。也就是说,人们希望时间和级别名称不再存在,但是它们已经存在了! enter image description here

同样,我不假装理解正在发生的事情,但是在我认为文档显示了简单继承的地方,我开始怀疑它的复杂性。 我在做什么错了?

当我纠正拼写错误并删除记录仪进行测试时,仍然会遇到相同的行为。启用传播,以便控制台日志到达root记录器,该记录器的[console_basic]仍使用旧格式显示消息。 enter image description here

对我的Yaml进行以下更改,似乎可以解决问题,如@blues所指出。

root:
    level: NOTSET
    handlers: [console_basic]
    propagate: no

loggers:
  __main__:
    level: DEBUG
    handlers: [console_basic]
    propagate: no

  Utils.paragraph_processing:
    level: DEBUG
    handlers: [info_file_handler, debug_file_handler, warn_file_handler, error_file_handler, critical_file_handler]
    propagate: no

  Utils.graphing_functions:
    level: DEBUG
    handlers: [info_file_handler, debug_file_handler, warn_file_handler, error_file_handler, critical_file_handler]
    propagate: no

1 个答案:

答案 0 :(得分:1)

这里有两件事。首先,配置中的propagate拼写错误。错误地拼写了prop o 门:请注意“ o”应在“ a”所在的位置。这意味着实际上所有记录器都将其日志沿层次结构传播。

第二件事是,当传播打开时,将忽略祖先记录器的级别(在本例中为根记录器),而仅考虑处理程序的级别。由于添加到root的console_err处理程序的级别为DEBUG,并且所有日志都传播到root,因此该处理程序将记录每个日志。

相关信息可在python文档here中找到:

消息直接传递给祖先记录器的处理程序- 所讨论的祖先记录器的级别和过滤器都不是 考虑过的。

相关问题