07-14 logging模块

01 logging

一. 日志级别与配置基本使用介绍

import logging

# 一:日志配置
"""
注意: 打开文件会发生乱码问题,它的内部运行原理可以理解为就是使用with open()打开文件且默认没有指定字符编码, 默认使用的是操作系统的GBK字符编码写入硬盘, 这个时候我们用文本编辑器打开"access.log"文件我们要使用GBK编码的方式来读。
logging.basicConfig: basicConfig指的是基本的配置
"""
logging.basicConfig(
    # 1、日志输出位置:1、终端 2、文件
    # 不指定,默认打印到终端(这种方式只能提供一种形式。如果你要往文件中输出就不能往终端中打印. 有局限性)
    filename='access.log',  

    # 2、日志格式
    # %(asctime)s   字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
    # %(name)s      Logger的名字, 没有指定默认就是root
    # %(levelname)s 文本形式的日志级别(debug调试, info信息, warning警告, error错误, critical危险)
    # %(module)s    调用日志输出函数的模块名
    # %(message)s   输出的消息
    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',

    # 3、时间格式
    # 这里的时间格式的指定是为了用来替代上面的asctime的时间格式
    datefmt='%Y-%m-%d %H:%M:%S %p',  
    # 4、日志级别
    # 级别数字对应的关系: 默认是warning级别,级别是对应的数字是30。由级别控制输出效果, 30级别只能输出30, 40, 50级别的内容及结果.
    # 10 --> debug
    # 20 --> info
    # 30 --> warning
    # 40 --> error
    # 50 --> critical
    level=10,
)
logging.debug('调试debug')
logging.info('消息info')
logging.warning('警告warning')
logging.error('错误error')
logging.critical('危险critical')
'''
# 注意: 下面的root是默认的日志名字, 没有指定,默认就是root。
WARNING:root:警告warn
ERROR:root:错误error
CRITICAL:root:严重critical
'''

二. 日志配置字典

# 1、定义三种日志输出格式,日志中可能用到的格式化串如下
"""
%(name)s             Logger的名字, 没有指定默认就是root
%(levelno)s          数字形式的日志级别(10, 20, 30, 40, 50)
%(levelname)s        文本形式的日志级别(debug调试, info信息, warning警告, error错误, critical危险)
%(pathname)s         调用日志输出函数的模块的完整路径名,可能没有
%(filename)s         调用日志输出函数的模块的文件名
%(module)s           调用日志输出函数的模块名
%(funcName)s         调用日志输出函数的函数名
%(lineno)d           调用日志输出函数的语句所在的代码行
%(created)f          当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d  输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s          字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d           线程ID。可能没有
%(threadName)s       线程名。可能没有
%(process)d          进程ID。可能没有
%(message)s          用户输出的消息
"""

# 2. 定义日志的输出格式: 强调!! 其中的%(name)s为调用logging模块后, 使用logging.getlogger()时指定的日志名
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]'

simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

test_format = '%(asctime)s] %(message)s'

# 3、日志配置字典
LOGGING_DIC = {
    # version 指定的是你的版本信息。
    'version': 1,

    # disable_existing_loggers 关闭已存在日志。默认False
    'disable_existing_loggers': False,

    # formatters 加s代表可以设置很多个不同的日志格式。(注意: 这个不能改,这个是固定的。)
    'formatters': {

        # standard, simple, test 主要目的是通过自定义这些名字让"handlers"中拿到下面自定义的日志格式的表现形式(提示: 自定义的日志格式命名可以修改)。
        'standard': {
            # format (注意: 这个不能改,这是固定的格式。)  # standard_format 这里可以指定你自定义的日志格式表现的形式。这里是一个变量, 代指的就是步骤2中定义的日志的输出格式.
            'format': standard_format
        },
        'simple': {
            'format': simple_format
        },
        'test': {
            'format': test_format
        },
    },
    'filters': {},

    # handlers 它是日志的接收者, 它用于控制日志的输出位置。不同的handler可以将日志输出到不同的位置.
    'handlers': {
        # console, default, other 这是你自定义的handler名(注意: 这里可以修改, 是你自定义的名字)

        # 输出位置: 打印到终端的日志, 由下面的class对应的logging.StreamHandler控制
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # class 指定日志输出的形式。(注意不能改。)打印到屏幕
            'formatter': 'simple'  # formatter 指定日志格式输出的形式, 会跑到上面formatters找到你之前所定义的格式simple。
        },

        # 输出位置: 打印到文件的日志, 由下面的class对应的logging.handlers.RotatingFileHandler控制
        'default': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',    # RotatingFileHandler 指定日志轮转, 由下面的maxBytes与backupCount互相组合使用, 防止日志文件内容过大, 读取困难(补充: 内部的底层原理就是当达到了轮转的要求, 就会把你指定的文件"a1.log"重命名, 再新建一个"a1.log"文件, 存放最新的日志内容.)。 # 日志轮转,的重要的意义在于当你的日志文件存储数据过大取的情况。不应该让你的日志在日志文件里不断的累加。如果你的日志文件过大几的话,你打开文件的话就会非常的慢。所以我们需要定期的分割。
            
            'formatter': 'standard',
            'filename': 'a1.log',
            # maxBytes 最大轮转值, 当达到了这个值, 日志文件就会轮转.默认单位是字节Bytes。这里计算出来是: 5M
            'maxBytes': 1024 * 1024 * 5,
            'backupCount': 5,  # backupCount 指的是最多给你保存几份, 当达到了保存限制, 会删除你最老的日志文件。
            'encoding': 'utf-8',  # 指定日志文件写入硬盘的编码.
        },

        # 输出位置: 你指定的文件"a2.log", 由下面的class对应的logging.FileHandler控制
        'other': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',  # FileHandler 指定日志输出的形式。输出到文件中。
            'formatter': 'test',
            'filename': 'a2.log',  # filename 既然要输出到文件中,那必须要指定文件路径,如果是在项目中,我们需要使用os.path等规范化路径。
            'encoding': 'utf-8',  # encoding 这里指定指定日志文件写入硬盘的编码.
        },
    },

    # loggers 它是日志的产生者, 负责产生不同级别的日志, 产生的日志会传递给上面的handlers中, 让handlers中的每个自定义的"handler"控制输出的位置。
    'loggers': {
        # logger
        # "logger"  指定''这种形式, 在执行logging.getLogger(key)时会判断,如果指定的key在下面的这些"logger"中都没找到, 就会把自定义key交给''中的"logger"处理, 处理以后, 交给上面的handlers进行处理
        '': {
            'handlers': ['default', 'console'],
            # handlers 这里指定你要交给的Handler路径, 交给"default"和"console"上面我们"handlers"中自定义的"handler"处理.
            'level': 'DEBUG',  # 这里又设置了日志级别,而handler中又设置了日志级别,这里有两层关卡。当使用logger_obj.info()这样的功能输入内容的时候. 会进行判断。如果日志级别满足,那么就会被收取到。满足以后会交给handlers中你自定义的"handler"来进行第二次筛选, 如果又满足,那么就会被你相应的"handler"功能, 进行处理。loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制)
            'propagate': False,  # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会将日志向上层层传递
        },

        # 这里为你专门的日志名进行提供服务, 在使用loggin.getlogger("日志名")时, 会跑到这里来匹配, 如果当时你指定的"日志名"与下面的key一致的时候就用使用下面的处理方式, 处理当前的日志. 当然没有匹配的情况下会跑到上面你什么都没指定''的里面去, 处理当前的日志, 以你指定的日志名作为你的日志名.
        '专门的采集': {
            'handlers': ['other', ],
            'level': 'DEBUG',
            'propagate': False,
        },
    },
}

三. 使用

# !!!强调!!!
# 1、logging是一个包,需要使用其下的config、getLogger,可以如下导入
# from logging import config  # 这里的config是logging下面的包。
# from logging import getLogger

# 2、也可以使用如下导入
import logging.config  # 这样连同logging.getLogger都一起导入了,然后使用前缀logging.config
import settings
# import logging.config

# 3、加载配置字典
logging.config.dictConfig(settings.LOGGING_DIC)

# 4、输出日志
logger1 = logging.getLogger('用户交易')  # getLogger: 可以拿到你定义的所有的loggers中定义的每个"logger"。
logger1.info('egon儿子alex转账3亿冥币')

# logger2=logging.getLogger('专门的采集') # 名字传入的必须是'专门的采集',与LOGGING_DIC中的配置唯一对应
# logger2.debug('专门采集的日志')
posted @ 2020-04-01 23:30  给你加马桶唱疏通  阅读(146)  评论(0编辑  收藏  举报