Python中如何使用logging模块记录日志

日志在实际生产工作中有着很重要的作用,之前一直不太注意这方面,导致生产环境遇到问题无从下手,借着整理把日志这块的功能熟悉下。网上有很多相关的介绍,不过还是建议大家浏览下官方相关的资料。官方文档的布局都差不多这里以3.8.12的版本为例:logging — Logging facility for Python — Python 3.8.12 documentation

文档对logging模块的功能整体上做了个简单的介绍,左边的红框说logging模块是线程安全的(进程不安全),如何解决多进程的问题在logging Cookbook(右边的红框)中有详细的介绍,也可以引入第三方包解决,后面会简单介绍下。

Basic Tutorial中有些基本的使用方法,Advanced Logging Tutorial中的LoggingFlow详细介绍了log日志信息的处理流程,简单理解就是logger负责生产日志,handle负责记录日志。

logging模块的使用有两种,一种是直接使用,一种是通过配置(python类或者是配置文件的方式这里归为一类)。这两种方法使用起来各有优点,直接使用配置会灵活些,创建响应的实例后可以直接修改属性,比如namer和suffix参数等等;配置文件的使用方式比较优雅,如果想做一些个性化的配置会比较麻烦些,可以自己创建对应的类来实现。

1、直接配置使用

 2、使用配置文件

使用配置文件也有几种不同的格式,这里主要是想介绍字典类型的dictConfig(该例子在Logging Cookbook)的使用,你直接使用图片中的代码是会报错的,需要把里面的owner字段去掉(你的电脑可能并不存在这两个用户)。

这里还要额外说明下dicConfig()的参数要求,这些都可以在官方文档中找到,这里简单介绍下主要的几个点。

logging.config — Logging configuration — Python 3.10.5 documentation

 1、version目前有效值为1(必要参数)。

后面的都是可选参数了:

2、‘()’代表自定义方法(实例)。

3、formatters格式化中定义日志相关的记录格式。

4、filters过滤器中定义日志过滤的条件,确认哪些日志需要保留。

5、handlers处理器中定义日志的输出方式,比如console控制台或者file文件以及输出日志的格式(format)。

6、loggers记录器中定义日志级别、过滤器以及日志处理器(handlers)。

7、root中进行根logger的配置,其配置可以被其他logger使用,可以理解为是父logger,其他的logger可以继承这个root的配置。所有的日志记录都会转发到root,如果logger中有等级配置,则这个转发的日志等级和root中的配置无关(root提供配置的继承)。由于有继承关系的存在,在大部分情况下同一个应用中并没有必要配置所有的logger。

8、incremental中进行额外配置的添加默认False。

9、disable_existing_loggers 中设置非root-loggers的可用性(不包括loggingConfigure中配置的loggers),不配置默认为True。

logger中日志的级别具有几个特点:1、可以继承父类的日志级别。2、配置的日志级别是大于关系,配置了DEBUG实际是配置了大于DEBUG的日志级别,如果要精确输出某种日志级别需要单独实现。

注意:采用配置文件的方式时要注意,配置文件中自定义函数的参数一定要是初始化函数的入参,属性或者方法并不支持直接在配置文件中配置。

附上一个配置示例,配置文件中添加了输出到console的配置(如果是debug状态需要输出到console)

import logging, logging.config, os
import time
import socket
from logging.handlers import TimedRotatingFileHandler
import logging.config




host_name = socket.gethostname()
sys_name = 'system_name'
# 获取当前脚本绝对路径
sys_path = os.path.abspath(__file__)
def owned_file_handler(log_level):
    # 获取当前路径作为日志存放路径
    log_dir = os.path.join(os.path.dirname(sys_path), 'logs')
    # 如果路径不存在创建对应路径
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)
    # 文件命名规则
    file_name = os.path.join(log_dir, '{}_{}_{}.log'.format(sys_name, log_level, host_name))
    # 滚动备份7个日志每天凌晨进行备份
    # file_handler = TimedRotatingFileHandler(file_name, when='midnight', backupCount=7, interval=1, encoding='utf-8')
    # 这里为了测试间隔1秒保存两个日志文件
    file_handler = TimedRotatingFileHandler(file_name, when='S', backupCount=2, interval=1, encoding='utf-8')
    # 配置日志文件后缀,如果想使用默认的数量管理对日志进行管理,日志日期的后缀格式为S'%Y-%m-%d_%H-%M-%S'
    # file_handler.suffix = '%Y-%m-%d_%H-%M-%S.log'
    return file_handler

# 添加debug函数用于调试的时候可以输出到console
def get_debug(debug):
    file_filter = logging.Filter()
    file_filter.filter = lambda debug: True
    return file_filter
# 添加日志级别的过滤
def owned_filter(log_levelno):
    file_filter = logging.Filter()
    file_filter.filter = lambda record: record.levelno == log_levelno
    return file_filter





LOGGING_SET = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'default': {
            # 设置日志格式以及时间格式
            'format': '[%(asctime)s:%(msecs)03d][{}][{}][%(module)s][%(process)d][%(thread)d]'
                      '----[%(levelname)s]---------%(message)s'.format(host_name, sys_name),
            'datefmt': '%Y-%m-%d-%H-%M-%S'
        },
    },
    'filters': {
        # 这里根据是否需要输出到console的实际使用情况进行配置
        'require_debug_true': {
            '()': get_debug,
            'debug': True
        },
        # 配置INFO级别的filter
        'filter_info': {
            '()': owned_filter,
            'log_levelno': logging.INFO
        },
        # 配置ERROR级别的filter
        'filter_error': {
            '()': owned_filter,
            'log_levelno': logging.ERROR
        }
    },
    'handlers': {
        # 配置console输出
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'default',
            'filters': ['require_debug_true'],

        },
        # 配置INFO级别的文件输出
        'file_info': {
            '()': owned_file_handler,
            'log_level': 'INFO',
            'formatter': 'default',
            'filters': ['filter_info']
        },
        # 配置ERROR级别的文件输出
        'file_error': {
            '()': owned_file_handler,
            'log_level': 'ERROR',
            'formatter': 'default',
            'filters': ['filter_error']
        }

    },
    # root可以获取所有日志信息,配置输出console,有必要的时候也可以配置输出到文件
    'root': {
        'handlers': ['console'],
        'level': 'DEBUG'

    },
    # 定义使用的logger:own_logger
    'loggers': {
        'own_logger': {
            'handlers': ['file_info', 'file_error'],
        },

    }
}



logging.config.dictConfig(LOGGING_SET)
own_logger = logging.getLogger('own_logger')


if __name__ == '__main__':
    for i in range(10):
        own_logger.debug('A debug message' * 10)
        own_logger.info('A info message' * 10)
        own_logger.error('A error message' * 10)

        time.sleep(1)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值