• Python3学习笔记25-logging模块


    logging模块,Python自带用来记录日志的模块。

    因为工作需要用到关于日志的,最近一直都在看关于日志模块的东西,百度了很多文章,可惜都是看的让人一头雾水,最后运气不错,找到一篇很详细的文章。传送门:https://www.cnblogs.com/testdjt/p/7834856.html

    logging模块默认定义了以下几个日志等级

    日志等级 (level) 描述
    DEBUG 最详细的日志信息,典型应用场景是 问题诊断
    INFO 信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作
    WARNING 当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的
    ERROR 由于一个更严重的问题导致某些功能不能正常运行时记录的信息
    CRITICAL 当发生严重错误,导致应用程序不能继续运行时记录的信息

    级别排序:CRITICAL > ERROR > WARNING > INFO > DEBUG >NOTSET 日志的信息量会依次减少

    当指定一个日志级别之后,会记录大于或等于这个日志级别的日志信息,小于的将会被丢弃



    Logging模块提供了两张记录日志的方式:

    第一种方式是使用logging提供的模块级别的函数

    第二种方式是使用Logging日志系统的四大组件

    logging模块定义的模块级别函数

    函数 说明
    logging.debug(msg, *args, **kwargs) 创建一条严重级别为DEBUG的日志记录
    logging.info(msg, *args, **kwargs) 创建一条严重级别为INFO的日志记录
    logging.warning(msg, *args, **kwargs) 创建一条严重级别为WARNING的日志记录
    logging.error(msg, *args, **kwargs) 创建一条严重级别为ERROR的日志记录
    logging.critical(msg, *args, **kwargs) 创建一条严重级别为CRITICAL的日志记录
    logging.log(level, *args, **kwargs) 创建一条严重级别为level的日志记录
    logging.basicConfig(**kwargs) 对root logger进行一次性配置

     

     

     

     

     

    import logging
    logging.debug("a")
    logging.info("b")
    logging.warning('c')
    logging.error('d')
    logging.critical('e')


    只有后面三个打印出来了,因为默认级别是logging.warning,低于该级别的就不输出了

    logging.basicConfig(level=logging.DEBUG)# 设置日志级别,需要大写
    logging.debug("a")
    logging.info("b")
    logging.warning('c')
    logging.error('d')
    logging.critical('e')


    Logging.basicConfig()需要在开头就设置,在中间设置没有作用

    通过logging.basicConfig可以设置root的日志级别,和日志输出格式。

     

     

    logging模块的四大组件

    组件名称 对应类名 功能描述
    日志器 Logger 提供了应用程序可一直使用的接口
    处理器 handler 将logger创建的日志记录发送到合适的目的输出
    过滤器 Filter 提供了更细粒度的控制工具来决定输出哪条日志记录,丢弃哪条日志记录
    格式器 Formatter 决定日志记录的最终输出格式

    logging模块提供的模块级别的那些函数实际上也是通过这几个组件的相关实现类来记录日志的只是在创建这些类的实例时设置了一些默认值

    这些组件之间的关系描述:

    日志器(logger)需要通过处理器(handler)将日志信息输出到目标位置,如:文件、sys.stdout、网络等;不同的处理器(handler)可以将日志输出到不同的位置;

    日志器(logger)可以设置多个处理器(handler)将同一条日志记录输出到不同的位置;

    每个处理器(handler)都可以设置自己的过滤器(filter)实现日志过滤,从而只保留感兴趣的日志;

    每个处理器(handler)都可以设置自己的格式器(formatter)实现同一条日志以不同的格式输出到不同的地方。

    简单点说就是:日志器(logger)是入口,真正干活儿的是处理器(handler),处理器(handler)还可以通过过滤器(filter)和格式器(formatter)对要输出的日志内容做过滤和格式化等处理操作。



    logger类

    a = logging.getLogger('mylogger')

    getLogger()返回一个logger实例,可以传入一个logger的名字,如果没有传,默认是root logger

    如果传了,比如这里是mylogger,在输出日志时候,就会显示是mylogger下的

    上面logging.info等,也是显示在root下的

    a.setLevel(logging.INFO)

    通过setLeverl()方法可以设置logger的日志输出级别

    a.debug('xxxxxx')
    a.info('cccccc')
    #Logger.addHandler() 和 Logger.removeHandler()    为该logger对象添加 和 移除一个handler对象
    #Logger.addFilter() 和 Logger.removeFilter()    为该logger对象添加 和 移除一个filter对象

    需要之前的logging.basicConfig()的设置,才会输出这个,因为logger的handler还没有加



    handler类

    通过handler对象可以把日志内容写到不同地方,python提供了十几种实用的handler,比较常用的有:

    类型 说明
    StreamHandler 输出到控制台
    FileHandler 输出到文件
    BaseRotatingHandler  可以按时间写入到不同的日志中。比如将日志按天写入不同的日期结尾的文件文件
    SocketHandler 用TCP网络连接写LOG
    DatagramHandler 用UDP网络连接写LOG
    SMTPHandler 把LOG写成EMAIL邮寄出去
    fh = logging.FileHandler('D:/lesson/test1.txt')#创建一个输出到文件的handler对象,这个对象叫fh
    fh.setLevel(logging.INFO)#给fh加上日志输出级别
    a.addHandler(fh)#给logger添加handler
    a.info('sfsdf')


    常用的方法

    Handler.setLevel()    设置handler将会处理的日志消息的最低严重级别
    Handler.setFormatter()    为handler设置一个格式器对象
    Handler.addFilter() 和 Handler.removeFilter()    为handler添加 和 删除一个过滤器对象

    Formater类

    字段/属性名称使用格式描述
    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 线程名称
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')#配置日志输出格式
    fh.setFormatter(formatter)#给handle加上格式
    a.info('1244555')

    formatter不像handler还需要先创建一个对应的实例,直接配置就可以了

    详细学习了logging模块之后,开始封装自己的log类

    1.需要把日志输出到指定路径,文件名为日期.log

    2.需要记录所有文件信息,并且报错信息单独存放,这需要不同的handler

    3.info和error需要不同的日志格式

    我的文件结构

    通过os.path.dirname(os.getcwd())获得项目名,也就是Vuiki。项目路径不同,使用的方法也不同。

    使用os.path.join()将路径进行拼接,形成日志存放的路径

    import logging
    import time
    import os
    
    class mylog(object):
        def __init__(self,logger_name):
    
            #创建一个logger
            self.logger= logging.getLogger(logger_name)
            self.logger.setLevel(logging.INFO)
    
    
            #设置日志存放路径,日志文件名
        #获取本地时间,转换为设置的格式
            rq = time.strftime('%Y%m%d%H%M',time.localtime(time.time()))
            #设置所有日志和错误日志的存放路径
            all_log_path = os.path.join(os.path.dirname(os.getcwd()),'Logs/All_Logs/')
            error_log_path = os.path.join(os.path.dirname(os.getcwd()),'Logs/Error_Logs/')
            #设置日志文件名
            all_log_name = all_log_path + rq +'.log'
            error_log_name = error_log_path + rq +'.log'
    
            #创建handler
            #创建一个handler写入所有日志
            fh = logging.FileHandler(all_log_name)
            fh.setLevel(logging.INFO)
            #创建一个handler写入错误日志
            eh = logging.FileHandler(error_log_name)
            eh.setLevel(logging.ERROR)
            #创建一个handler输出到控制台
            ch = logging.StreamHandler()
            ch.setLevel(logging.INFO)
    
            #定义日志输出格式
            #以时间-日志器名称-日志级别-日志内容的形式展示
            all_log_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
            #以时间-日志器名称-日志级别-文件名-函数行号-错误内容
            error_log_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(module)s  - %(lineno)s - %(message)s')
            #将定义好的输出形式添加到handler
            fh.setFormatter(all_log_formatter)
            ch.setFormatter(all_log_formatter)
            eh.setFormatter(error_log_formatter)
    
    
            #给logger添加handler
            self.logger.addHandler(fh)
            self.logger.addHandler(eh)
            self.logger.addHandler(ch)
    
        def getlog(self):
            return self.logger

    下面是测试代码

    from Common import logger
    logger = logger.mylog('test').getlog()
    try:
        logger.info('开始测试...')
        r = 10/0
        logger.info('result:',r)
    except ZeroDivisionError as e:
        logger.error('tests',exc_info=1)
    logger.info('end')

    这是输出到控制台的日志信息

    这是所有的日志信息

    这是错误的日志信息

    使用exc_info=1可以把报错信息完整的打印进日志

  • 相关阅读:
    【 DCOS 】织云 CMDB 管理引擎技术详解
    腾讯云无服务器云函数架构精解
    深度学习在 CTR 中应用
    一文教你迅速解决分布式事务 XA 一致性问题
    小程序开发工具全新上线
    秦俊:开放 DevOps 敏捷开发套件,助力开发者驰骋云端
    张兴华:云端架构助力企业快速成长
    王磊:AI 时代物流行业的 OCR 应用
    陈杰:无服务器架构,让云端开发更纯粹
    腾讯织云:DevOps 流水线应用平台践行之路
  • 原文地址:https://www.cnblogs.com/myal/p/9337405.html
Copyright © 2020-2023  润新知