Python——Logging 模块

目录

一、logging模块的日志级别

1、日志级别

2、代码实现

二、logging模块的使用方式

1、logging提供的模块级别的函数

1.1 记录日志级别

1.2 logging.basicConfig(**kwargs)

2、logging日志系统的四大组件

2.1 Logger

2.2 Handler

2.3 Filter

2.4 Formatter

三、示例解析

1、最终代码

2、常见的问题


一、logging模块的日志级别

1、日志级别

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

2、代码实现

import logging

logging.debug('debug message')
logging.info('info message')
logging.warning('waining message')
logging.error('error message')
logging.critical('critical message')

结果:

我们发现,只显示了大于等于WARNING级别的日志。

也就是说,日志等级级别为:CRITICAL > ERROR > WARNING > INFO > DEBUG

二、logging模块的使用方式

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

  • 第一种方式是使用logging提供的模块级别的函数
  • 第二种方式是使用Logging日志系统的四大组件

1、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进行一次性配置

1.1 记录日志级别

logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical():分别用以记录不同级别的日志信息。

1.2 logging.basicConfig(**kwargs)

logging.basicConfig():用默认日志格式为日志系统创建一个默认的流处理器。

logging.basicConfig()源文件中写到:

也就是说,参数为:

  • filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
  • filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
  • format:指定handler使用的日志显示格式。
  • datefmt:指定日期时间格式。
  • level:设置rootlogger(后边会讲解具体概念)的日志级别。
  • stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。

下面我们来举个例子:

import logging

# 改变日志类别,日志格式,日志位置
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    filename='D:/Pycharm_Project/test_python/log/test2.log',
                    filemode='w')

logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')

输出结果:在test2.log文件中

 

关于format参数中可能用到的格式化串,在这里我简单介绍一下:

  • %(name)s:Logger的名字
  • %(levelno)s:数字形式的日志级别
  • %(levelname)s:文本形式的日志级别
  • %(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、logging日志系统的四大组件

组件说明
loggers提供应用程序代码直接使用的接口
handlers用于将日志记录发送到指定的目的位置
filters提供更细粒度的日志过滤功能,用于决定哪些日志记录将会被输出(其它的日志记录将会被忽略)
formatters用于控制日志信息的最终输出格式

2.1 Logger

1、Logger是一个树形层级结构,输出信息之前都需要获得一个Logger(如果没有显示的获取,则自动创建并使用root Logger)

2、logger  = logger.getLogger()返回一个默认的Logger,即root Logger

def getLogger(name=None):
    """
    Return a logger with the specified name, creating it if necessary.

    If no name is specified, return the root logger.
    """
    if name:
        return Logger.manager.getLogger(name)
    else:
        return root

3、 层次化的实现,就是通过在名称上加点(.)

4、setLevel()指定最低的日志级别,可用的日志级别有logging.DEBUG、logging.INFO、logging.WARNING、logging.ERROR、logging.CRITICAL。

5、示例

# 创建一个logger
logger  = logging.getLogger()

logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG)

logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.INFO)

logger3 = logging.getLogger('mylogger.child1')
logger3.setLevel(logging.WARNING)

logger4 = logging.getLogger('mylogger.child1.child2')
logger4.setLevel(logging.DEBUG)

logger5 = logging.getLogger('mylogger,child1.child2.child3')
logger5.setLevel(logging.DEBUG)

2.2 Handler

1、Handler对象的作用是将消息分发到handler指定的位置(文件、网络、邮件等)。

2、Logger对象可以通过addHandler()方法为自己添加0个或者更多个handler对象。

3、常见的Handler:

Handler描述
logging.StreamHandler将日志消息发送到输出到Stream,如std.out, std.err或任何file-like对象。
logging.FileHandler将日志消息发送到磁盘文件,默认情况下文件大小会无限增长
logging.handlers.RotatingFileHandler将日志消息发送到磁盘文件,并支持日志文件按大小切割
logging.hanlders.TimedRotatingFileHandler将日志消息发送到磁盘文件,并支持日志文件按时间切割
logging.handlers.HTTPHandler将日志消息以GET或POST的方式发送给一个HTTP服务器
logging.handlers.SMTPHandler将日志消息发送给一个指定的email地址
logging.NullHandler该Handler实例会忽略error messages,通常被想使用logging的library开发者使用来避免'No handlers could be found for logger XXX'信息的出现。

4、 示例:

在这里,我创建了两个常用的handler:

(1)logging.FileHandler()

# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('D:/Pycharm_Project/test_python/log/test3.log')

(2)logging.StreamHandler()

# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()

2.3 Filter

1、限制只有满足过滤规则的日志才会输出。

2、示例:

#定义一个filter
filter = logging.Filter('mylogger.child1.child2')
fh.addFilter(filter)

2.4 Formatter

1、Formatter对象设置日志信息最后的规则、结构和内容,默认的时间格式为%Y-%m-%d %H:%M:%S。 

2、示例:

# 定义handler的输出格式formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)

注:最后我们需要添加handler到logger,并且记录日志

(1)添加handler到logger

# 添加handler到logger
# logger.addHandler(filter)
logger.addHandler(fh)
logger.addHandler(ch)

# logger.addHandler(filter)
logger1.addHandler(fh)
logger1.addHandler(ch)

logger2.addHandler(fh)
logger2.addHandler(ch)

# logger3.addFilter(filter)
logger3.addHandler(fh)
logger3.addHandler(ch)

# logger4.addFilter(filter)
logger4.addHandler(fh)
logger4.addHandler(ch)

# logger5.addFilter(filter)
logger5.addHandler(fh)
logger5.addHandler(ch)

(2)记录日志

# 记录日志
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message')

logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')

logger3.debug('logger3 debug message')
logger3.info('logger3 info message')
logger3.warning('logger3 warning message')
logger3.error('logger3 error message')
logger3.critical('logger3 critical message')

logger4.debug('logger4 debug message')
logger4.info('logger4 info message')
logger4.warning('logger4 warning message')
logger4.error('logger4 error message')
logger4.critical('logger4 critical message')

logger5.debug('logger5 debug message')
logger5.info('logger5 info message')
logger5.warning('logger5 warning message')
logger5.error('logger5 error message')
logger5.critical('logger5 critical message')

三、示例解析

1、最终代码

#coding:utf-8
import logging

# 创建一个logger
logger  = logging.getLogger()

logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG)

logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.INFO)

logger3 = logging.getLogger('mylogger.child1')
logger3.setLevel(logging.WARNING)

logger4 = logging.getLogger('mylogger.child1.child2')
logger4.setLevel(logging.DEBUG)

logger5 = logging.getLogger('mylogger,child1.child2.child3')
logger5.setLevel(logging.DEBUG)

# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('D:/Pycharm_Project/test_python/log/test3.log')

# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()

# 定义handler的输出格式formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)

#定义一个filter
#filter = logging.Filter('mylogger.child1.child2')
#fh.addFilter(filter)

# 添加handler到logger
# logger.addHandler(filter)
logger.addHandler(fh)
logger.addHandler(ch)

# logger.addHandler(filter)
logger1.addHandler(fh)
logger1.addHandler(ch)

logger2.addHandler(fh)
logger2.addHandler(ch)

# logger3.addFilter(filter)
logger3.addHandler(fh)
logger3.addHandler(ch)

# logger4.addFilter(filter)
logger4.addHandler(fh)
logger4.addHandler(ch)

# logger5.addFilter(filter)
logger5.addHandler(fh)
logger5.addHandler(ch)

# 记录日志
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message')

logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')

logger3.debug('logger3 debug message')
logger3.info('logger3 info message')
logger3.warning('logger3 warning message')
logger3.error('logger3 error message')
logger3.critical('logger3 critical message')

logger4.debug('logger4 debug message')
logger4.info('logger4 info message')
logger4.warning('logger4 warning message')
logger4.error('logger4 error message')
logger4.critical('logger4 critical message')

logger5.debug('logger5 debug message')
logger5.info('logger5 info message')
logger5.warning('logger5 warning message')
logger5.error('logger5 error message')
logger5.critical('logger5 critical message')

2、常见的问题

(1)运行结果

在这里我们只展示一部分结果,发现在输出控制台和日志文件中均显示。

下面我们将逐渐分析。

(2)问题1:

logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')

输出:

 

这里只显示出了三行信息,说明默认只输出≥WARNING级别的信息。

(3)问题2:

logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG)

logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.INFO)

输出:

 我们发现这两部分是相同的,均是输出≥INFO级别的信息。

虽然我们在前面设置了logger1.setLevel(logging.DEBUG),但是logger2.setLevel(logging.INFO)将其设置为INFO的级别,因此没有显示出DEBUG级别的日志信息。

(4)问题3:

我们发现logger1、logger2对应的每个输出分别显示了2次,logger3对应的输出显示了3次,logger4对应的输出显示了4次,以此类推...

 原因:

logger = logging.getLogger()创建了root Logger

logger1 = logging.getLogger('mylogger')创建了root Logger的孩子

logger2 = logging.getLogger('mylogger')创建了root Logger的孩子

logger3 = logging.getLogger('mylogger.child1')创建了mylogger的孩子

logger4 =  logging.getLogger('mylogger.child1.child2')创建了mylogger.child1的孩子

logger5 = logging.getLogger('mylogger.child1.child2.child3')创建了mylogger.child1.child2的孩子

他们之间的关系是:

logger --> logger1(logger2) --> logger3 --> logger4 --> logger5

logger2和logger1同为logger的孩子,他们之间的关系是兄弟关系,此处不举例了。

因此每一次输出,均继承父类。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值