zoukankan      html  css  js  c++  java
  • 🍖logging 模块

    一.什么是 logging 模块

    • logging 模块是 Python 自带的标准模块

    二.logging 模块有什么作用

    • 主要用于输出运行日志
    • 可以控制输出日志的等级, 过滤一些重要信息, 不显示大量无关要紧的调试信息
    • 日志保存的路径, 可以是输出到终端, 也可以是输出到文件
    • 以及文件轮转等等, 日志文件轮转指的是设置保存日志文件个数, 当超过最大日志文件个数, 最早的那个日志文件会被删除

    三.logging 模块的使用

    1.直接导入 logging 模块

    import logging
    
    先进行日志的基本配置
    logging.basicConfig(
                # filename='access.log',          # 日志名字 (不指定默认输出到终端)
                format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s', # 日志格式
                datefmt='%Y-%m-%d %H:%M:%S %p',   # 时间格式
                level=30,                         # 日志等级
                )
    
    进行日志输出
    logging.debug('在大楼使用电子设备')          # 10  调试信息
    logging.info('大楼里面使用打火机')           # 20  正常运行信息
    logging.warning('大楼里抽烟')               # 30 警告  可能出错
    logging.error('正在大楼里玩火')             # 40 出错
    logging.critical('拿着手榴弹在大楼里溜达')   # 50 出错长时间不管会崩溃
    ''' 输出结果
    2020-12-11 19:50:30 PM - root - WARNING - test: 大楼里抽烟
    2020-12-11 19:50:30 PM - root - ERROR - test: 正在大楼里玩火
    2020-12-11 19:50:30 PM - root - CRITICAL - test: 拿着手榴弹在大楼里溜达
    '''
    通过日志等级过滤掉了"debug"以及"info"的日志信息 (大于以及等于你设置的那个等级才会输出)
    

    四.logging 模块的四种对象

    1.logger : 负责生产日志

    logger1 = logging.getLogger('[日志名]')
    

    2.fitter : 过滤日志 (不常用)

    玉炉香  红蜡泪  偏照画堂秋思
    

    3.handler : 控制日志输出的位置 (文件or终端)

    fh1 = logging.FileHandler(filename='a1.log', encoding='utf-8')  # 文件a1
    fh2 = logging.FileHandler(filename='a2.log', encoding='utf-8')  # 文件a2
    sh = logging.StreamHandler()  # 终端
    

    4.formatter : 控制日志的格式

    formatter1 = logging.Formatter(
        fmt='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(massage)s',  # 日志输出格式
        datefmt='%Y-%m-%d %H:%M:%S %p',  # 时间格式
    )
    
    • 日志输出格式

    属性名称 使用格式 作用
    asctime %(asctime)s 日志事件发生的时间--人类可读时间,如:2003-07-08 16:49:45,896
    created %(created)f 日志事件发生的时间--时间戳,就是当时调用time.time()函数返回的值
    relativeCreated %(relativeCreated)d 日志事件发生的时间相对于logging模块加载时间的相对毫秒数(目前还不知道干嘛用的)
    msecs %(msecs)d 日志事件发生事件的毫秒部分
    levelname %(levelname)s 该日志记录的文字形式的日志级别('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
    levelno %(levelno)s 该日志记录的数字形式的日志级别(10, 20, 30, 40, 50)
    name %(name)s 所使用的日志器名称,默认是'root',因为默认使用的是 rootLogger
    message %(message)s 日志记录的文本内容,通过 msg % args计算得到的
    pathname %(pathname)s 调用日志记录函数的源码文件的全路径
    filename %(filename)s pathname的文件名部分,包含文件后缀
    module %(module)s filename的名称部分,不包含后缀
    lineno %(lineno)d 调用日志记录函数的源代码所在的行号
    funcName %(funcName)s 调用日志记录函数的函数名
    process %(process)d 进程ID
    processName %(processName)s 进程名称,Python 3.1新增
    thread %(thread)d 线程ID
    threadName %(thread)s 线程名称

    五.日志字典配置

    #自定义日志的输出格式
    formatter1_format = '%(asctime)s %(name)s %(filename)s:%(lineno)d %(levelname)s: %(message)s'
    formatter2_format = '%(asctime)s %(name)s : %(message)s'
    formatter3_format = '%(asctime)s : %(message)s'
    
    #通过变量的方式存放路径,也可以使用"os.path"来规范路径
    logfile_path1 = r'F:\Pycharm File\PycharmProjects\python正课\day18\a1.log'  # log文件名
    logfile_path2 = r'F:\Pycharm File\PycharmProjects\python正课\day18\a2.log'  # log文件名
    
    #log配置字典, 里面就是上面提到的四种对象
    LOGGING_DIC = {
        'version': 1,                       # 指定版本信息
        'disable_existing_loggers': False,  # 关闭已存在日志。默认False
    #    控制日志的格式
        'formatters': {                      # 固定格式不能修改  
            "formatter1": {                  # 开头自定义的日志输出格式名
                'format': formatter1_format  # "format" 固定格式不能修改
            },
            'formatter2': {
                'format': formatter2_format  
            },
            'formatter3': {
                'format': formatter3_format  
            },
        },
    #    过滤日志 (不常用)
        'filters': {},
    #    控制日志输出的位置
        'handlers': {                            
            'file1_hanlder': {                   # 自定义"handlers"名字,可以改
                'level': 'DEBUG',                # 日志过滤等级
                'class': 'logging.FileHandler',  # 保存到文件里面去(日志保存的形式)
                'formatter': 'formatter1',       # 绑定的日志输出格式
                'filename': logfile_path1,       # 制定日志文件路径
                'encoding': 'utf-8',             # 日志文件的编码,不再担心乱码问题
            },
            'file2_hanlder': {
                'level': 'DEBUG',
                'class': 'logging.FileHandler',  
                'formatter': 'formatter2',
                'filename': logfile_path2,  
                'encoding': 'utf-8',  
            },
            'terminal': {                        # 自定义的"handlers"名字(终端)             
                'level': 'DEBUG',                # 日志过滤等级
                'class': 'logging.StreamHandler',# 打印到屏幕
                'formatter': 'formatter3'        # 日志输出格式
            },
        },
    #    负责生产日志
        'loggers': {
            # '' 代表默认的,在执行'logging.getLogger("key")'时,在"loggers"里面没有找到这个"key"时就使用这个
            '': {  
                # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
                'handlers': ['file1_hanlder', 'file2_hanlder','terminal'],  
                'level': 'DEBUG',
                'propagate': False,  # 向上(更高level的logger)传递,默认True, 通常设置为False
            },
            # 在执行'logging.getLogger("key")'时,在"loggers"里面找到这个"key"时就使用这个
            '自定义日志名1': {  
                'handlers': ['terminal'],  
                'level': 'DEBUG',
                'propagate': False, 
            },
            '自定义日志名2': {  
                'handlers': ['file2_hanlder','terminal'],  
                'level': 'INFO',
                'propagate': False,
            },
        },
    }
    

    六.导入字典模块来进行使用

    image-20201211210815394

    先导入"setting.py"以及"logging.config"
    import logging.config
    from conf import setting
    
    加载配置字典
    logging.config.dictConfig(setting.LOGGING_DIC)
    
    测试一:
    logger1 = logging.getLogger('自定义日志名1')  # 执行后回去日志字典的"logger"里面找这个'自定义日志名1'(key)
    logger1.info('派大星向海绵宝宝转账 : $1000000万')
    测试二:
    logger2 = logging.getLogger('自定义日志名2')
    logger2.error('派大星向章鱼哥转账 : $1000000万')
    测试三:
    logger3 = logging.getLogger('找不到就默认')
    logger3.info('派大星向蟹老板转账 : $1000000万')
    
    ''' 日志输出结果
    2020-12-11 21:13:10,758 : 派大星向海绵宝宝转账 : $1000000万
    2020-12-11 21:13:10,758 : 派大星向章鱼哥转账 : $1000000万
    2020-12-11 21:13:10,758 : 派大星向蟹老板转账 : $1000000万
    '''
    

    七.日志级别的两层关卡

    • 第一层是 logger 中设置的日志级别

    • 第二层是 handler 中设置的日志级别

    当使用"logger_obj.info("XXXX")"/"logger_obj.error("XXXX")"等等这样的功能输入内容的时候
    "logger"中的日志等级会进行判断/过滤如果日志级别满足,那么就会被收取到
    满足以后会交给"handlers"中你自定义的"handler"日志等级来进行第二次过滤
    如果又满足,那么就会被你相应的"handler"功能进行处理
    

    八.日志功能在实际应用中的简单示例

    • 以下只是截取了程序的一小段来做演示(倒数第二行为记录日志)
    from db import db_handler
    from lib import common
    
    def register_interface(name, password, balance=15000):
        '''
        注册接口.
        :param name:用户名
        :param password: 密码
        :param balance: 确认密码
        :return:True,False
        '''
        user_dic = db_handler.select(name)
        if user_dic:
            return False, '用户已存在'
        else:
            user_dic = {'name': name, 'password': password, 'balance': balance,
                        'locked': False, 'bankflow': [], 'shoppingcart': {}}
            db_handler.save(user_dic)
            user_logger.info('用户%s注册成功' % name)  # 如果注册成功就会记录这个用户的注册信息日志
            return True, '注册成功'
    

    完整代码可参考 ATM 简单项目实现

    Github完整项目下载

  • 相关阅读:
    【软件构造】Lab1基本流程指导及重难点分析
    【软件构造】关于java中List和Set数据结构不同实现方式和不同遍历方式时间效率的探讨与分析
    程序人生-Hello’s P2P
    WinterCamp2017吃饭睡觉记
    bzoj 3144 [Hnoi2013]切糕
    bzoj 1565 [NOI2009]植物大战僵尸
    bzoj 1061 [Noi2008]志愿者招募
    序列
    Philosopher
    时机成熟之时
  • 原文地址:https://www.cnblogs.com/songhaixing/p/14122825.html
Copyright © 2011-2022 走看看