python dictConfig封裝自定義日誌器優化(三)

Holidayzz發表於2020-11-22

之前使用dictConfig寫了自定義日誌器的封裝,但感覺不是很好,責任劃分不明確,邊在實踐中進行優化,把日誌的一部分配置(如日誌檔名、路徑等)摘出來放在專案配置檔案中,其他配置依舊放在yaml檔案中維護。

如有不對或可優化的點,歡迎指出!

日誌器封裝demo

1. 從專案配置檔案中讀取日誌相關配置內容

  • content of src __init__.py
# content of src __init__.py

# -*- coding: utf-8 -*-
# @Time    : 2020/11/15 2:51 下午
# @Author  : holidaylzz

import os
import jsonpath
import yaml.scanner

SETTING_DIR = '專案配置檔案絕對路徑'

# 單例,專案配置檔案
with open(file=SETTING_DIR, mode='r') as file:
    setting_content = yaml.safe_load(file.read())

    
def __load_logfile_config():
    """
    讀取專案日誌配置
    :return:
    """
    # 專案絕對路徑
    project_dir = jsonpath.jsonpath(setting_content, '$.project.dir')
    if not project_dir:
        raise TypeError('project dir error,please check setting file!')
    # 改變當前目錄至專案目錄
    os.chdir(project_dir[0])

    # logging.yaml檔案
    logging_yaml_dir = jsonpath.jsonpath(setting_content, '$.log_config.logging_yml_dir')
    if not logging_yaml_dir:
        raise TypeError('logging_yml_dir error,please check setting file!')
    logging_yaml_abs_dir = os.path.abspath(logging_yaml_dir[0])

    # 日誌檔案路徑
    log_dir = jsonpath.jsonpath(setting_content, '$.log_config.dir')
    if not log_dir:
        raise TypeError('log dir error,please check setting file!')
    log_abs_dir = os.path.abspath(log_dir[0])

    # 日誌檔名
    log_filename = jsonpath.jsonpath(setting_content, '$.log_config.filename')
    if not log_filename:
        raise TypeError('log filename error,please check setting file!')
    log_filename = log_filename[0]

    return logging_yaml_abs_dir, log_abs_dir, log_filename


# 日誌檔案配置,單例
logfile_config = __load_logfile_config()

2. 從日誌yaml配置檔案讀取相關配置資訊,用於logging.config.dictConfig()配置日誌器

  • content of src/conf __init__.py
# content of src/conf __init__.py
# -*- coding: utf-8 -*-
# @Time    : 2020/11/15 3:09 下午
# @Author  : holidaylzz

import yaml

from src import logfile_config


__all__ = ["logging_content"]


# logging content,單例
with open(file=logfile_config[0], mode='r') as file:
    logging_content = yaml.safe_load(file.read())

3. 自定義日誌器封裝

# -*- coding: utf-8 -*-
# @Time    : 2020/11/15 3:11 下午
# @Author  : holidaylzz
# @desc    : logger optimization

import os
import logging
from logging.config import dictConfig


from src import logfile_config
from src.conf import logging_content


__all__ = ['LogUtil']


class LogUtil(object):

    def __init__(self, logger_name, log_path=logfile_config[1], log_filename=logfile_config[2]):
        """
        :param logger_name: 日誌器名稱
        :param log_path:日誌存放路徑
        :param log_filename:日誌檔名稱
        """

        # 新建日誌檔案目錄,一定要新建這個目錄否則會FileNotFoundError
        os.makedirs(log_path, exist_ok=True)

        # 遍歷config的handlers,修改filename,加上路徑
        for handler, handler_value in logging_content['handlers'].items():
            if handler_value['level'] == 'INFO':
                handler_value['filename'] = os.path.join(log_path, log_filename)
                continue
            if handler_value['level'] == 'ERROR':
                # 通過切片找到errorlog
                handler_value['filename'] = os.path.join(log_path, f'{log_filename[:-4]}_error.log')
                continue
            if handler_value['level'] == 'WARN':
                # 通過切片找到warnlog
                handler_value['filename'] = os.path.join(log_path, f'{log_filename[:-4]}_warn.log')
                continue
        # 配置logging
        logging.config.dictConfig(logging_content)
        self.__logger = logging.getLogger(logger_name)

    @property
    def logger(self):
        return self.__logger

yaml配置檔案

  • content of src/conf logging
# version must be 1
# logger配置檔案
#################################### logging yaml content #############################################

version: 1
disable_existing_loggers: False
formatters:
        simple:
            format: "%(asctime)s - %(thread)d - [%(levelname)s] %(pathname)s - %(module)s - %(funcName)s: %(message)s"
#filters:
handlers:
    info_file_timedRotatingFileHandler:
            class: logging.handlers.TimedRotatingFileHandler
            level: INFO
            formatter: simple
            filename: runner.log
            when: 'midnight'
            backupCount: 7
            encoding: utf8
    error_file_timedRotatingFileHandler:
            class: logging.handlers.TimedRotatingFileHandler
            level: ERROR
            formatter: simple
            filename: runner_error.log
            when: 'midnight'
            backupCount: 7
            encoding: utf8
    warn_file_timedRotatingFileHandler:
            class: logging.handlers.TimedRotatingFileHandler
            level: WARN
            formatter: simple
            filename: runner_warn.log
            when: 'midnight'
            backupCount: 7
            encoding: utf8
root:
    level: INFO
    handlers: [info_file_timedRotatingFileHandler,error_file_timedRotatingFileHandler,warn_file_timedRotatingFileHandler]

專案配置檔案

  • content of setging file
# version must be 1
# project setting file
version: 1
project:
    desc: "專案描述"
    dir: "專案部署絕對路徑"
log_config:
    filename: runner.log
    dir: log
    logging_yml_dir: "src/conf/logging"

相關文章