【记录】Python日志模块

本文深入探讨了Python的logging模块,介绍了如何配置和使用logging模块来记录不同级别的日志信息,包括日志格式的规范性、日志级别的定义以及三种配置logging的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python日志处理(logging模块)

日志追踪程序运行时候发生的事件,开发当中在程序中添加logging模块,记录程序日志log。通过log的分析,可以方便用户了解系统或者软件的运行状况;
如果你的应用log足够丰富,也可以分析以往用户的操作行为、类型喜好、地域分布或其他更多信息;

日志的记录

一条日志信息对应的是一个事件的发生,而一个事件通常需要包括以下几个内容:

  • 事件发生的时间
  • 事件发生的位置
  • 事件的严重程度–日志级别
  • 事件的内容

说明:日志格式的规范性能帮助开发人员快速定位,当然针对不同的需求,可以包含其他信息,输入一条日志时候,日志内容和日志级别是需要开发人员明确支出的,对于其他字段信息,按需。

日志级别

不同的应用程序所定义的日志等级可能会有所差别,分的详细点的会包含以下几个等级:

  • DEBUG
  • INFO
  • NOTICE
  • WARNING
  • ERROR
  • CRITICAL
  • ALERT
  • EMERGENCY

重点:日志功能的实现(logging模块介绍)

几乎所有的开发语言都会内置日志相关功能,或者会有比较优秀的第三方库来提供日志操作功能,比如:log4j, log4php等。
python自身也提供了一个用于记录日志的标注模块logging

logging模块的使用方法介绍

作为开发者,我们可以通过以下三种方式来配置logging:

  • 使用python代码显式的创建loggers, handlers,和formatters并分别调用他们的配置函数;
  • 创建一个日志配置文件,然后使用fileConfig()函数来读取该文件的内容;
  • 创建一个包含配置信息的dict, 然后把它传递给dictConfig()函数

需要说明的是, logging.basicConfig()也属于第一种方式,它只是对loggers, handleers和formatters的配置函数进行了封装。另外,第二种配置方式相对于第一种配置方法的优点在于,他将配置信息和代码进行了分离,之一方面降低了日志的维护成本,同时还使得非开发人员能够很容易的去修改日志配置。

方式一
def logs_method1(filePath):
    """
    写日志方式1, 1)使用Python代码显式的创建loggers, handlers和formatters并分别调用它们的配置函数;

    :return:
    """
    # 创建一个日志器logger并设置其日志级别为DEBUG
    logger = logging.getLogger('simple_logger')
    logger.setLevel(logging.DEBUG)

    # 创建一个流处理器handler并设置其日志级别为DEBUG
    handler = logging.StreamHandler(open(filePath,'a'))
    handler.setLevel(logging.DEBUG)

    # 创建一个格式器formatter并将其添加到处理器handler
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    handler.setFormatter(formatter)

    # 为日志器logger添加上面创建的处理器handler
    logger.addHandler(handler)

    # # 日志输出
    # logger.debug('debug message')
    # logger.info('info message')
    # logger.warn('warn message')
    # logger.error('error message')
    # logger.critical('critical message')
    return logger
方式二
def logs_method2():
    """
    写日志方法2 :  2)创建一个日志配置文件,然后使用fileConfig()函数来读取该文件的内容;
    :return:
    """
    # 读取日志配置文件内容
    logging.config.fileConfig('logs/log_config/logging.conf')

    # 创建一个日志器logger
    logger = logging.getLogger('simpleExample')

    # 日志输出
    # logger.debug('debug message 22')
    # logger.info('info message 22')
    # logger.warn('warn message 22')
    # logger.error('error message 22')
    # logger.critical('critical message 22')
    return logger

配置文件:

#logger.conf

###############################################

[loggers]
keys=root,simpleExample

[handlers]
keys=consoleHander,errorFileHander,logFileHander


[formatters]
keys=form01,form02,form03
#################################################
[logger_root]
level=DEBUG
handlers=consoleHander

[logger_simpleExample]
level=DEBUG
handlers=consoleHander,errorFileHander,logFileHander
qualname=simpleExample
propagate=0


###############################################

[handler_consoleHander]
class=StreamHandler
args=(sys.stdout,)
level=DEBUG
formatter=form03


[handler_errorFileHander]
class=FileHandler
level=ERROR
formatter=form03
encoding='utf8'
args=('logs/log_record/error.log', 'a')


[handler_logFileHander]
class=logging.handlers.RotatingFileHandler
level=INFO
formatter=form03
encoding='utf8'
args=('logs/log_record/log.log', 'a', 500*1024*1024, 5)


###############################################
[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
datefmt=%a, %d %b %Y %H:%M:%S

[formatter_form02]
format=%(name)-12s: %(levelname)-8s %(message)s
datefmt=%a, %d %b %Y %H:%M:%S

[formatter_form03]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
配置文件格式说明
  • 配置文件中一定要包含loggers, handlers,formatters 这些section;他们通过keys这个option来指定该配置文件中已经定义好的loggers, handlers和formatters, 多个值之间用逗号分隔; 另外 loggers这个section中的keys 一定要包含root这个值;
  • loggers、handlers、formatters中所指定的日志器、处理器和格式器都需要在下面以单独的section进行定义。seciton的命名规则为[logger_loggerName]、[formatter_formatterName]、[handler_handlerName]
  • 定义logger的section必须指定level和handlers这两个option,level的可取值为DEBUG、INFO、WARNING、ERROR、CRITICAL、NOTSET,
  • 对于非root logger来说,除了level和handlers这两个option之外,还需要一些额外的option,其中qualname是必须提供的option,它表示在logger层级中的名字,在应用代码中通过这个名字得到logger;查找不到名字时候会使用上级的配置;propagate是可选项,其默认是为1,表示消息将会传递给高层次logger的handler,通常我们需要指定其值为0,这个可以看下下面的例子;另外,对于非root logger的level如果设置为NOTSET,系统将会查找高层次的logger来决定此logger的有效level。
  • 定义handler的section中必须指定class和args这两个option,level和formatter为可选option;class表示用于创建handler的类名,args表示传递给class所指定的handler类初始化方法参数
    ,它必须是一个元组(tuple)的形式,即便只有一个参数值也需要是一个元组的形式;level与logger中的level一样,而formatter指定的是该处理器所使用的格式器,这里指定的格式器名称必须出现在formatters这个section中,且在配置文件中必须要有这个formatter的section定义;如果不指定formatter则该handler将会以消息本身作为日志消息进行记录,而不添加额外的时间、日志器名称等信息;
    定义formatter的sectioin中的option都是可选的,其中包括format用于指定格式字符串,默认为消息字符串本身;datefmt用于指定asctime的时间格式,默认为’%Y-%m-%d %H:%M:%S’;class用于指定格式器类名,默认为logging.Formatter;

记录

记录自定义的脚本;完成日志的配置;可以满足大部分的开发需求:
在自己项目中导入该包就行;

init_logger.py

# coding:utf-8
"""
@author: Finks
@time: 2021/2/1 17:11

"""

import os
import logging
from logging import Logger
from logging.handlers import TimedRotatingFileHandler

'''
日志模块
1. 同时将日志打印到屏幕跟文件中
2. 默认值保留近30天日志文件
'''


def init_logger(log_dir, log_name=None):
    # default value
    if log_name == None: log_name = 'Log.log'
    assert isinstance(log_name, str), f'log_name require string..but got {type(log_name)}'

    logger = logging.getLogger(log_name)
    logger.setLevel(logging.DEBUG)

    # file handler for info
    handler = TimedRotatingFileHandler(filename=os.path.join(log_dir, log_name), when='D', backupCount=30)
    date_fmt = '%Y-%m-%d %H:%M:%S'
    format_str = '[%(asctime)s] - %(filename)s [line:%(lineno)s] [%(levelname)s]: %(message)s'
    formatter = logging.Formatter(format_str, date_fmt)
    handler.setFormatter(formatter)
    handler.setLevel(logging.INFO)
    logger.addHandler(handler)

    # console handler
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    console.setFormatter(formatter)
    logger.addHandler(console)

    # file handler for error
    handler = TimedRotatingFileHandler(filename=os.path.join(log_dir, "ERROR_{}".format(log_name)), when='D',
                                       backupCount=30)
    date_fmt = '%Y-%m-%d %H:%M:%S'
    format_str = '[%(asctime)s] - %(filename)s [line:%(lineno)s] [%(levelname)s]: %(message)s'
    formatter = logging.Formatter(format_str, date_fmt)
    handler.setFormatter(formatter)
    handler.setLevel(logging.ERROR)
    logger.addHandler(handler)

    return logger


if __name__ == "__main__":
    logger = init_logger(log_dir=r'C:\Users\ymchen.Finks\Desktop')
    logger.info("test")
    logger.error("test2")

快捷方式

直接拷入这部分代码;可以满足大部分的需求;

    import logging
    from logging import handlers
    # 日志路径
    log_file = 'log.log'
    logger = logging.getLogger(log_file)
    # 设置日志等级
    logger.setLevel(logging.INFO)
    # 设置写入格式
    fmt = '%(asctime)s - %(filename)s[line:%(lineno)d] - [%(levelname)s]: %(message)s'
    # 定义往文件中写入句柄和往屏幕上写入的句柄, 并设置格式(when: 设置间隔时间单位,backCount:保留日志的个数,超过数量会删除)
    t_handler = logging.handlers.TimedRotatingFileHandler(filename=log_file, when='D', backupCount=30)
    s_handler = logging.StreamHandler()
    t_handler.setFormatter(logging.Formatter(fmt))
    s_handler.setFormatter(logging.Formatter(fmt))
    # 添加句柄,完成配置!
    logger.addHandler(s_handler)
    logger.addHandler(t_handler)



    logger.error('错误')
    logger.info('你好!')

带颜色的日志

# coding:utf-8
"""
@author: Finks
@time: 2021/6/3 21:07

"""
import logging
import colorlog


log_colors_config = {
    'DEBUG': 'white',  # cyan white
    'INFO': 'green',
    'WARNING': 'yellow',
    'ERROR': 'red',
    'CRITICAL': 'blue',
}


logger = logging.getLogger('Log')

# 输出到控制台
console_handler = logging.StreamHandler()
# 输出到文件
file_handler = logging.FileHandler(filename='Log', mode='a', encoding='utf8')


logger.setLevel(logging.DEBUG)
console_handler.setLevel(logging.DEBUG)
file_handler.setLevel(logging.INFO)

# 日志输出格式
file_formatter = logging.Formatter(
    fmt='[%(asctime)s.%(msecs)03d  %(levelname)08s] : %(message)s',
    datefmt='%Y-%m-%d  %H:%M:%S'
)
console_formatter = colorlog.ColoredFormatter(
    fmt='%(log_color)s[%(asctime)s.%(msecs)03d %(levelname)08s] : %(message)s',
    datefmt='%Y-%m-%d  %H:%M:%S',
    log_colors=log_colors_config
)
console_handler.setFormatter(console_formatter)
file_handler.setFormatter(file_formatter)

# 重复日志问题:
# 1、防止多次addHandler;
# 2、loggername 保证每次添加的时候不一样;
# 3、显示完log之后调用removeHandler
if not logger.handlers:
    logger.addHandler(console_handler)
    logger.addHandler(file_handler)

console_handler.close()
file_handler.close()


if __name__ == '__main__':
    logger.debug('debug')
    logger.info('info')
    logger.warning('warning')
    logger.error('error')
    logger.critical('critical')


​🐱​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值