美文网首页
Python39_日志处理

Python39_日志处理

作者: jxvl假装 | 来源:发表于2019-09-28 10:55 被阅读0次

    logging模块

    日志基础

    日志级别(从低到高):

    1. logging.NOTSET:不设置

    2. loging.debug:最详细的日志信息,通常用于问题诊断

    3. logging.info:信息的详细程度仅次于debug,通常记录关键节点的信息,用于确认一别都是按照预期的那样进行工作

    4. logging.warning:当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的

    5. logging.error:由于一个更严重的问题导致某些功能不能正常运行时记录的信息

    6. logging.critical:致命错误,导致程序不能继续运行时记录的信息

    注意:logging的默认级别为warning

    日志包含的内容

    1. 事件发生的时间

    2. 事件发生的位置

    3. 事件的严重程度(日志的级别)

    4. 事件的内容

    logging模块提供的两种记录日志的方式

    1. 使用logging提供的模块级别的函数(其实也是对logging日志系统相关类的封装而已)

    2. 使用logging日志系统的四大组件

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

    import logging
    
    #创建不同严重级别的的日志记录
    logging.debug(msg, *args, **kwargs)
    logging.info(msg, *args, **kwargs)
    logging.warning(msg, *args, **kwargs)
    logging.error(msg, *args, **kwargs)
    logging.critical(msg, *args, **kwargs)
    
    logging.log(level, *args, **kwargs) #创建一条严重级别为level的日志记录
    logging.basicConfig(**kwargs)   #对root logger进行一次性配置
    
    

    `其中logging.basicConig(**kwargs)函数用于指定“要记录的日志级别”、“日志格式”、“日志输出位置”、“日志文件的打开模式”等信息

    logging.basicConfig()函数说明

    该方法用于为logging日志系统做一些基本配置,方法定义如下:
    logging.basicConfig(**kwargs)

    filename:指定日志输出目标文件的文件名,指定后日志内容就不会输出到控制台
    filemode:指定日志文件的打开模式,默认为“a”,即追加。需要在指定filename时才有效
    format:指定日志格式字符串,即指定日志输出时所包含的字段信息以及他们的顺序。
    datefmt:dateformat的缩写。指定日期/时间格式。需要在format中包含时间字段%(asctime)s时才有效
    level:指定日志器的日志级别
    stream:指定日志输出目标stream,如sys.stdout、sys.stderr以及网络stream。stream和filename不能同时提供,否则引发ValueError错误
    style:指定format格式字符串的风格,可取值为"%"、"{"、和"$",默认为"%"
    handlers:该选项如果被指定,它应该是一个创建了多个Handler的可迭代对象,这些handler将会被添加到root logger。filename、stream、handlers这三个配置只能有一个存在,否则引发ValueError异常
    
    

    logging模块定义的格式字符串(format参数)字段

    1. %(asctime)s:日志发生的时间,人类可读时间,如:2019-06-29

    2. %(created)f:日志事件发生的时间——时间戳,即调用time.time()函数返回的值

    3. %(relativeCreated)d:日志事件发生的时间相对于logging模块加载时间的相对毫秒数

    4. %(msecs)d:日志事件发生的毫秒部分

    5. %(levelname)s:该日志记录的文字形式的日志级别(DEBUG,INFO,WARNING,ERROR,CRITICAL)

    6. %(levelno)s:该日志记录的数字形式的日志级别(10,20,30,40,50)

    7. %(name)s:所使用的日志器的名称,默认是"root",因为默认使用的root logger

    8. %(message)s:日志记录的文本内容,通过msg % args计算得到

    9. %(pathname)s:调用日志记录函数的源码文件的全部路径

    10. %(filename)s:pathname的文件名部分,包含文件后缀

    11. %(module)s:filename的名称部分,不包含后缀

    12. %(lineno)d:调用日志记录函数的源代码所在的行号

    13. %(funcName)s:调用日志记录函数的函数名

    14. %(process)d:进程ID

    15. %(processName)s:进程名称

    16. %(thread)d:线程ID

    17. %(threadName)s:线程名称

    其他说明

    1. logging.basicConfig()函数是一个一次性的简单配置工具,即:只有在第一次调用该函数时会起作用,后续再次调用该函数时完全不会产生任何操作,多次调用的设置不是累加操作

    2. 日志器(logger)是有层级关系的,上面调用的logging模块级别的函数所使用的日志器是RootLogger类的实例,其名称为“root”,处于日志器层级关系最顶层,且以单例模式存在

    3. 如果要记录的日志中包含变量数据,可使用一个格式字符串作为这个事件的描述信息(logging.debug、logging.info等函数的第一个参数),然后将变量数据作为第二个参数*args的值进行传递,eg:logging.warning("%s is %d years old"%, "Tom",23)

    4. logging.debug()、logging.info()等方法的定义中,除了msg和args参数外,还有一个**kwargs参数,他们支持3个关键兹参数:exc_info,stack_info,extra

      1. exc_info:值为布尔类型,如果为True,就会将异常信息添加到日志消息中,如果没有异常信息则添加None到日志信息中

      2. stack_info:值为布尔类型,默认为False,如果参数设置为True,栈信息会被添加到日志信息中

      3. extra:这是一个字典(dict)参数,可以用来自定义消息格式所包含的字段,但是他的key不能与logging模块定义的字段冲突

    logging模块的四大组件

    1. loggers:提供应用程序代码直接使用的接口

    2. handlers:用于将日志记录发送到指定的目的位置

    3. filters:提供更详细的日志过滤功能,用于决定哪些日志记录将会被输出(其他的日志了会被忽略)

    4. formatters:控制日志信息的最终输出格式

    四大组件的关系:

    1. 日志器(logger)需要通过处理器(handler)将日志新出目标位置,如:文件、sys.stdout、网络等

    2. 不同的处理器(handler)可以将日志输出到不同的位置

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

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

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

    logging的使用

    可以通过logging模块定义的模块级别的方法去完成简单的日志记录

    只有级别大于或等于日志记录器指定级别的日志记录才会被输出,小于该级别的日志记录将会 被丢弃

    logging日志模块相关类及其常用方法介绍

    • Logger类常用方法:
    1. Logger.setLevel():设置日志器将会处理的日志消息的最低严重级别

    2. Logger.addHandler()和Logger.removeHandler():为logger对象添加和移除一个handler对象

    3. Logger.addFilter()和Logger.removeFilter():为logger对象添加一移除一个filter对象

    logger对象配置完成后,可以使用下面的方法来创建日志记录:

    1. Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():创建一个与其方法名对应等级的日志记录

    2. Logger.exception():创建一个类似于Logger.error()的日志消息

    3. Logger.log():需要获取一个明确的日志level参数来创建一个日志记录

    如何得到一个Logger对象?:logging.getLogger(name = "root"),如果以相同的name参数多次调用getLogger方法,将会返回指向同一个Logger对象的引用

    关于logger的层级结构与有效等级的说明:

    1. logger的名称是一个以"."分割的层级结构,每个"."后面的logger都是"."前面的loggerd children,例如:有一个名称为foo的logger,foo.bar,foo.bar.baz都是foo的后代

    2. logger有一个“有效等级(effective level)”的概念。如果一个logger上没有被明确设置一个level,那么该logger 会使用他parent的level,root logger总是会有一个明确的level设置(默认为warning)

    3. child loggers在完成对耳垂处理后,默认会将日志消息传递给他们的祖先loggers相关的handlers,因此,我们不必为一个应用程序中所使用的所有loggers定义和配置handlers,只需要为一个顶层的logger配置handlers,然后按照需要创建child loggers就可足够。我们也可通过将一个logger的propagate属性设置为False来关闭这种传递机制

    • Handler类:

    Handler对象的作用是(基于日志消息的level)将消息分发到handler指定的位置(文件、网络、邮件)。Logger对象可以通过addHandler来为自己添加0个或多个handler对象。如:一个应用程序要想实现以下几个日志需求:

    1. 把所有日志都发送到一个日志文件中

    2. 把所有严重级别大于等于error的日志发送到stdout(标准输出)

    3. 把所有严重级别软critical的日志发送到一个email邮件地址

    这种场景就需要3个不同的handlers,每个handlers负责发送一个特定严重级别的日志到一个特定位置

    hanlder常用配置方法:

    1. Handler.setLevel():设置handler将会处理的日志消息的最低严重级别

    2. Handler.setFormatter():为handler设置一个格式器对象

    3. Handler.addFilter()和Handler.removeFilter():为handler添加和删除一个过滤器对象

    注意:应用程序代码不应该直接实例化和使用Handler实例。因为Handler是一个基类,它只定义了所有handlers都应该有的接口,痛楚提供了一些子类可以直接使用或覆盖的默认行为。

    常用Handler:

    1. logging.StreamHandler:将日志消息发送Stream,如:std.out,std,err或任何file-like对象

    2. logging.FileHandler:将日志消息发送到磁盘文件,默认情况下文件大小会无限增长

    3. logging.handlers.RotationFileHandler:将日志消息发送到磁盘,并支持日志文件按大小切割

    4. logging.hanlders.TimedRotatingFileHandler:将日志消息发送到磁盘文件,并支持日志文件按时间切割

    5. logging.handlers.HTTPHandler:将日志消息发送给一个指定的HTTP服务器

    6. logging.handlers.SMTPHandler:将日志消息发送给一个指定的email地址

    7. logging.NullHandler:该Handler会忽略error messages,通常被想使用logging的library开发者用来避免"No handlers could be found for logger xxx"信息的出现

    • Formater类

    Formater对象用于配置日志信息的最终顺序、结构和内容。与logging.Handler基类不同的是,应用代码可以直接实化Formatter类。另外,如果你的应用程序需要一些特殊的处理行为,也可以实现一个Formatter的子类来完成

    Formatter类的构造方法定义如下:logging.Foratter.__init__(fmt=None, datefmt = None, style = '%')

    1. fmt:指定消息格式化字符串,如果不制定该参数则默认使用message的原始值

    2. datefmt:指定日期格式字符串,默认:"%Y-%m-%d- %H:%M:%S"

    3. style:可取值为"%`、%{、$",如果不指定则默认使用"%"

    • Filter类

    Filter可以被Handler和Logger用来做比level更细粒度的、更复杂的过滤功能。Filter是一个过滤器基类,只允许某个logger层级下的日志事件通过过滤。该类定义如下:

    class logging.Filter(name = "")
        filter(record)
    
    

    比如,一个filter实例化时传递的name参数值为"A.B",那么该filter实例将只允许名称为类似如下规则的loggers产生的日志记录通过过滤:"A.B","A.B.C",而名称为"A.BB"的loggers产生的日志则会被过滤掉。如果name的值为空字符串,则允许所有的日志事件通过过滤

    filter方法用于具体控制传递的record记录是否能通过过滤,如果该方法返回值为0,表示不能通过过滤,返回值非0表示可以通过过滤。

    ps:如果有需要,也可以在filter(record)方法内部改变该record,比如添加、删除或修改一些属性。

    最简单的日志输出

    法一:

    import logging
    
    log_format = "%(asctime)s-%(levelname)s-%(message)s"    #注意小括号及其后的s
    date_formate = "%m-%d-%Y %H:%M:%S%p"
    logging.basicConfig(level=logging.DEBUG,filename="test.log",
                        datefmt=date_formate,format=log_format)
    #以不同的级别输出
    logging.debug("This is a debug...")
    logging.info("This is a info...")
    logging.warning("This is a warning...")
    logging.error("This is a error...")
    logging.critical("This is a critical...")
    
    

    以上代码在Test.log文件的输出结果如下

    06-29-2019 20:44:47PM-DEBUG-This is a debug...
    06-29-2019 20:44:47PM-INFO-This is a info...
    06-29-2019 20:44:47PM-WARNING-This is a warning...
    06-29-2019 20:44:47PM-ERROR-This is a error...
    06-29-2019 20:44:47PM-CRITICAL-This is a critical...
    
    

    法二:

    import logging
    log_format = "%(asctime)s-%(levelname)s-%(message)s"    #注意小括号及其后的s
    date_formate = "%m-%d-%Y %H:%M:%S%p"
    logging.basicConfig(level=logging.DEBUG)    #从debug输出,由于没有设置filename,所以从控制台输出
    logging.log(logging.DEBUG,"This is a debug")
    logging.log(logging.INFO,"This is a info")
    logging.log(logging.WARNING,"This is a warning")
    logging.log(logging.ERROR,"This is a error")
    logging.log(logging.CRITICAL,"This is a critical")
    

    控制台输出内容如下:

    DEBUG:root:This is a debug  #日志级别:日志器名称:日志内容
    INFO:root:This is a info
    WARNING:root:This is a warning
    ERROR:root:This is a error
    CRITICAL:root:This is a critical
    

    使用四大组件记录日志

    import logging
    import logging.handlers
    import datetime
    
    logger = logging.getLogger("my_logger")
    logger.setLevel(logging.DEBUG)
    
    rf_handler = logging.handlers.TimedRotatingFileHandler("all.log", when="midnight", interval=1,
                                                           backupCount=7, atTime=datetime.time(0, 0, 0, 0))
    
    rf_handler.setFormatter(logging.Formatter("%(asctime)s-%(levelname)s-%(message)s"))
    
    f_handler = logging.FileHandler("error.log")
    f_handler.setLevel(logging.ERROR)
    f_handler.setFormatter(logging.Formatter("%(asctime)s-%(levelname)s-%(filename)s[:%(lineno)d]-%(message)s"))
    
    logger.addHandler(rf_handler)
    logger.addHandler(f_handler)
    
    logger.debug("This is a debug...")
    logger.info("This is a info...")
    logger.warning("This is a warning...")
    logger.error("This is a error...")
    logger.critical("This is a critical...")
    

    在all.log中的输出内容如下:

    2019-06-30 15:32:21,707-DEBUG-This is a debug...
    2019-06-30 15:32:21,707-INFO-This is a info...
    2019-06-30 15:32:21,708-WARNING-This is a warning...
    2019-06-30 15:32:21,708-ERROR-This is a error...
    2019-06-30 15:32:21,708-CRITICAL-This is a critical...
    

    在error.log中的输出内容如下:

    2019-06-30 15:32:21,708-ERROR-python高级功能之日志处理.py[:135]-This is a error...
    2019-06-30 15:32:21,708-CRITICAL-python高级功能之日志处理.py[:136]-This is a critical...
    

    相关文章

      网友评论

          本文标题:Python39_日志处理

          本文链接:https://www.haomeiwen.com/subject/jvhuuctx.html