Python неправильно настроены регистраторы / обработчики? - PullRequest
0 голосов
/ 28 мая 2020

Хотя я уже некоторое время работаю с python / i python, я считаю себя новичком. Есть еще много вещей, особенно о поддержке журналирования, как я думал, я понял из документации, но, по-видимому, их сложнее настроить, чем я ранее надеялся. Я использую 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 Ответ

1 голос
/ 28 мая 2020

Здесь происходят две вещи. Прежде всего, в конфиге есть неправильное написание propagate. Неправильно написано prop o gate: обратите внимание на «o», где должна быть «a». Это означает, что все регистраторы фактически распространяют свои журналы вверх по иерархии.

Во-вторых, когда распространение включено, уровень регистраторов предков, в данном случае регистратора root, игнорируется и Учитывается только уровень обработчиков. Поскольку обработчик console_err, добавляемый к root, имеет уровень DEBUG и все журналы распространяются на root, этот обработчик будет регистрировать каждый журнал.

Соответствующую информацию можно найти в python документация здесь :

Сообщения передаются непосредственно обработчикам регистраторов предков - ни уровень, ни фильтры соответствующих регистраторов предков не учитываются.

...