python logging模块

日志管理模块——logging模块,是Python的内置模块。

1、日志级别

import logging

logging.debug('调试日志')
logging.info('消息日志')
logging.warning('警告日志')
logging.error('错误日志')
logging.critical('严重错误日志')

运行结果:
在这里插入图片描述
默认的日志输出级别是WARNING,只打印WARNING级别以上的日志,WARNING级别以下的INFO和DEBUG日志未输出。

root是日志的名字,可更改。

2、日志基本配置

import logging

# 日志基本配置
logging.basicConfig(
    # 1、日志级别
    level=10,
    # DEBUG 10
    # INFO  20
    # WARNING   30
    # ERROR 40
    # CRITICAL  50

    # 2、日志输出格式
    # asctime 获取当前时间;name 当前日志名字;pathname   指的是哪一个文件产生的日志;lineno    指的是这个文件的哪一行产生的这个日志;
    # levelname 日志等级;message    日志的具体内容
    # 输出格式:2022-12-14 14:05:22,997 root [E:/practice/日志管理.py line:26 DEBUG 调试日志]
    # 997是毫秒,若不想要,可通过设置asctime的时间格式来更改
    format='%(asctime)s %(name)s [%(pathname)s line:%(lineno)d %(levelname)s %(message)s]',

    # 3、asctime的时间格式
    datefmt='%Y-%m-%d %H:%M:%S',


    # 4、日志输出位置:终端/文件
    filename='user.log',   # 不指定此配置,默认打印到终端;指定后会在当前路径下产生一个user.log文件,日志输出到该文件中,不会打印到终端
)

'''
%(name)s            Logger的名字(getlogger时指定的名字)
%(levelno)s         数字形式的日志级别
%(levelname)s       文本形式的日志级别
%(pathname)s        调用日志输出日志的完整路径名
%(filename)s        调用日志输出日志的文件名
%(module)s          调用日志输出日志的模块名
%(funcName)s        调用日志输出日志的函数名    
%(lineno)d          调用日志输出函数的语句所在的代码行
%(created)f         当前时间,用UNIX标准的表示时间的浮点数表示
%(relativeCreated)d 输出日志信息时的自Logger创建以来的毫秒数
%(asctime)s         字符串形式的当前时间,默认格式是”2022-12-24 15:37:53,394“
%(thread)d          线程ID,可能没有
%(threadName)s      线程名,可能没有
%(process)d         进程ID,可能没有
%(message)s         用户输出的信息
'''

# 日志级别
logging.debug('调试日志')
logging.info('消息日志')
logging.warning('警告日志')
logging.error('错误日志')
logging.critical('严重错误日志')

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在PyCharm中打开user.log文件,出现乱码。–写入日志时没有指定字符编码,日志基本配置logging.basicConfig()无法设置字符编码。未指定字符编码,默认使用Windows系统的编码方式gbk,而PyCharm默认是用utf-8打开的,所以会乱码。
在这里插入图片描述

3、日志配置字典

日志配置字典可解决:
1、字符编码问题
2、把日志信息既往文件里面写,同时还在终端输出一份

把logging模块所需要的各方面配置都写在配置字典里,通过加载这个字典,让logging模块使用这里面的配置项。

'''
logging模块有三个比较重要的功能组件:
    1、loggers        配置文件可定义一些输出日志的appname
    2、handler        配置日志的分隔大小、输出位置、日志文件创建等
    3、formatters     配置日志输出的格式
'''

LOGGING_DIC ={
    'version': 1.0,
    'disable_existing_loggers': False,

    # 日志格式
    'formatters': {
        'standard': {
            'format': '%(asctime)s %(threadName)s:%(thread)d [%(name)s] %(levelname)s [%(pathname)s:line:%(lineno)d]  %(message)s',
            'datefmt': '%Y-%m-%d %H:%M:%S',
        },
        'simple': {
            'format': '%(asctime)s [%(name)s] %(levelname)s %(message)s',
            'datefmt': '%Y-%m-%d %H:%M:%S',
        },
        'test': {
            'format': '%(asctime)s %(message)s',
        },
    },
    'filters': {},

    # 日志处理器
    # logger负责生产不同级别的日志,然后把日志丢给handler。而handler就是把logger生产的日志进行处理,是输出到控制台还是写入到文件,是写入到文件a还是写入到文件b,都是由handler控制。
    # 可设置多个handler,不同的handler做不同的处理。
    'handlers': {
        # 把日志输出到终端,同时日志等级是debug
        'console_debug_handler': {
            'level': 'WARNING',   # 日志处理的级别限制
            # 'level': 10,
            'class': 'logging.StreamHandler',   # 输出到终端
            'formatter': 'simple'   # 日志格式
        },

        # 'file_info_handler': {},
        'file_debug_handler': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',  # 保存到文件
            'filename': 'text.log',  # 日志存放的路径
            'encoding': 'utf-8',  # 日志文件的编码
            'formatter': 'test',
        },

        'file_deal_handler': {
            'level': 'INFO',
            'class': 'logging.FileHandler',  # 保存到文件
            'filename': 'deal.log',  # 日志存放的路径
            'encoding': 'utf-8',    # 日志文件的编码
            'formatter': 'standard',
        },

        'file_operate_handler': {
            'level': 'INFO',
            'class': 'logging.FileHandler',  # 保存到文件
            'filename': 'operate.log',  # 日志存放的路径
            'encoding': 'utf-8',  # 日志文件的编码
            'formatter': 'standard',
        },
    },

    # 日志记录器
    'loggers': {
        'logger1': {
            'handlers': ['console_debug_handler'],  # 日志分配到哪个handelrs中
            'level': 'INFO',    # 日志记录的级别限制
            'propagate': False  # 默认为True,向上(更高级别的logger)传递,设置为False即可,否则会一份日志向上层层传递
        },

        # 'logger2': {
        #     'handlers': ['console_debug_handler', 'file_debug_handler'],
        #     'level': 'INFO',
        #     'propagate': False,
        # },

        'logger3': {
            'handlers': ['console_debug_handler', 'file_deal_handler'],
            'level': 'INFO',
            'propagate': False,
        },

        'logger4': {
            'handlers': ['console_debug_handler', 'file_operate_handler'],
            'level': 'INFO',
            'propagate': False,
        },
    },
}

4、日志使用

logging本身是一个包,而logging下面有一个子包叫config,不能直接logging.config
在这里插入图片描述
上图原因是:logging模块的设计者没有把config这个名字导入到logging的__init__.py里面。因为导logging导的就是logging下面的__init__.py。

可通过from logging import config,不但可以找logging的__init__里面的名字,还可以找logging文件夹里的名字。

# import logging
# from logging import config
import logging.config
import setting

logging.config.dictConfig(setting.LOGGING_DIC)
logger1 = logging.getLogger('logger3')
logger1.info('xxx充值了5毛钱')

logger2 = logging.getLogger('logger4')
logger2.info('xxx登录了')

'''
注释掉import logging,将无法使用logging下面的功能。from logging import config导入的是config,logging根本没导入。

from logging import config,虽然logging没导入,但是logging下面的init文件也是运行过的。
因为from logging这种方式,会先检索logging的init里面有没有config,要检索init就一定会执行一遍init。如果init里面没有config,才会在logging文件夹里找。

虽然执行了logging下面的init,但是用不了logging下面的功能。因为只是执行了init,并没有导入logging,也就是并没有导入logging下的init。

import logging.config和from logging import config一样,同样也会先执行logging下的init,看看有没有config这个名字,如果没有再找logging这个文件夹下面的模块名。但和from logging import config不同的是,import logging.config会导入logging。
'''

5、日志轮转

由于程序产生的日志,记录的是程序运行过程中的一些关键信息,这些信息是不能够轻易删除的,有可能这个日志很多年都没有用过,也不能去删除它,因为不知道哪天哪个用户会出问题,有可能前脚刚把日志删了,后脚用户就来找麻烦了。所以日志一定不能随便删。

但是随着软件生命周期的不断拉长,日志文件可能会非常大。如果日志文件过大,打开文件查看时就会非常卡,所以不应该一直把日志往同一个文件里写。

当日志文件内容增长到一定量时,就把它里面原有的内容给剪切到另外一个文件里存着。

日志轮转:当某个日志文件deal.log增长到一定量时,就把这个文件重命名一下,下次再产生新日志时,就又会重新创建一个deal.log。

# 日志轮转
'file_info_handler': {
   'level': 'INFO',
   'class': 'logging.handlers.RotatingFileHandler',    # 保存到文件
   'filename': 'deal.log',
   # 'maxBytes': 1024*1024*10,   # 日志文件大小 10M    当日志文件达到多大时,就进行日志轮转  默认单位是字节
   'maxBytes': 800,
   'backupCount': 3,  # 日志文件保存数量限制
   'encoding': 'utf-8',
   'formatter': 'standard',
},

报错:PermissionError: [WinError 32] 另一个程序正在使用此文件,进程无法访问。: ‘E:\practice\deal.log’ -> ‘E:\practice\deal.log.1’

程序在把deal.log重命名为deal.log.1时,deal.log被另一个程序占用着。
在这里插入图片描述

解决办法:
在日志轮转fiel_into_hanlder中处理的文件是deal.log,在file_deal_handler中处理的文件也是deal.log,即便没有logger在调用file_deal_handler,也会把这个文件给占用着。

deal.log被占用的情况下不能够重命名。进行日志轮转的文件必须是独一无二的,不能够和其他handler共用。
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值