Python学习之路(32)——日志处理模块logging

一、什么是日志?

日志是一种可以追踪某些软件运行时所发生事情的方法。我们在代码中调用日志记录相关的方法来表明发生了的事件。一个事件可以用一个包含可选变量数据的消息来描述。另外,事件也有严重性级别,包括:Debug、Info、Notice、Warning、Error、Critical、Alert、Emergency。一个时间通常包括以下内容:事件发生的时间、事件发生的位置、事件的级别、事件内容。

 

二、logging模块

1、logging模块的级别:

1)DEBUG:最详细的日志信息,典型应用场景是问题诊断

2)INFO:信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照预期进行

3)WARNING:当某些不期望的事件发生时记录的信息,但此时应用程序还是可以正常运行

4)ERROR:由于一个严重的问题导致某些功能不能正常运行时记录的信息

5)CRITICAL:当发生严重错误,导致应用程序不能继续运行时记录的信息

注意:以上日志等级逐步升高,而日志的信息量是逐步减少的;当为某个应用程序指定一个日志级别后,应用程序会记录所有大于或等于指定级别的日志信息。

2、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进行一次性配置,用于指定“要记录的日志级别”、“日志格式”、“日志输出位置”、“日志文本的打开模式”等消息。

2)logging模块的4大组件

Logger:记录器,提供应用程序代码直接使用的接口

Handler:处理器,用于将日志记录发送到指定的目的位置

Filter:过滤器,提供更细颗粒度的日志过滤功能,用于记得哪些日志记录将被输出(其他日志被忽略)

Formatter:格式化器,用于控制日志信息的最终输出格式

注意:实际上logging模块的模块函数也是通过这几个组件的相关实现类来记录日志的

 

三、使用函数记录日志

1、最简单的日志输出

#!/usr/local/bin/python
# -*- coding:utf-8 -*-
import logging

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

##########
输出结果:
WARNING:root:warn message
ERROR:root:error message
CRITICAL:root:critical message

默认情况下,logging模块将日志打印到屏幕上(stdout),日志级别为WARNING(即高于WARNING的日志信息才会输出),且日志格式为默认的BASIC_FORMAT(日志级别:logger实例名称:日志内容)。

2、logging.basicConfig()进行简单配置

logging.basicConfig(**kwargs):为logging日志做一些基本配置

可接受的参数包括:

通过简单的配置输出方式和日志级别

#!/usr/local/bin/python
# -*- coding:utf-8 -*-
import logging

# 通过下面的方式进行简单配置输出方式与日志级别
logging.basicConfig(filename='logger.log', level=logging.INFO,format=LOG_FORMAT)

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


##############
输出结果:
打印台没有结果
本地当前目录下生成logger.log文件,内容为:
2018-03-13 14:38:07,854 - INFO - info message
2018-03-13 14:38:07,854 - WARNING - warn message
2018-03-13 14:38:07,854 - ERROR - error message
2018-03-13 14:38:07,854 - CRITICAL - critical message

  

注意:

logging.basicConfig()函数是一个一次性简单配置工具,只有在第一次调用时才起作用。

记录器logger是有层次关系的,最顶层的日志器是RootLogger类的实例,名称为root,以单例模式存在。

日志中可使用一个格式字符串作为事件的描述消息,然后将变量数据作为第二个参数*args的值进行传递。

>>> import logging
>>> logging.warning('%s is studing %s.', 'nicolas', 'Python')
WARNING:root:nicolas is studing Python.

  

四、4大组件

1、Logger记录器:

Logger是一个树形层级结果,在使用接口debug、info、warn、error、critical之前必须创建Logger实例(创建一个记录器),如果没有显式的创建则默认会创建一个root looger,并应用默认日志级别(warning),处理器Handler(StreamHandler,即日志打印到标准输出上)和格式化器Formatter(默认格式)。

import logging
logger = logging.getLogger("nicolas")    #创建名为nicolas的记录器
logger.setLevel(logging.ERROR)        #设置日志级别为ERROR
logger.addHandler("handler_name1")      #为Logger实例增加一个处理器
logger.removeHandler("handler_name1")    #为Logger实例删除一个处理器
logger.addFilter("filter_1")          #为Logger实例增加一个过滤器
logger.removeFilter("filter_1")        #为Logger实例删除一个过滤器
logger.debug()
logger.info()
....
logger.cirtical()
logger.exception()                #创建一个类似于logger.error()的日志消息,输出堆栈追踪消息
logger.log()                   #需要获取一个明确的日志level参数来创建一个日志记录

2、Handler处理器:

Handler常用三个处理器类型:StreamHandler、FileHandler、NullHandler。

常用方法:

import logging
handler = logging.StreamHandler(stream = None)
#handler = logging.FileHandler(filename, mode='a', encoding=None, delay=False)
handler.setLevel()                #设置handler实例将会处理的日志消息的最低级别
handler.setFormatter()          #为handler实例设置应格式化器对象
handler.addFilter()                #为handler实例增加一个过滤器
handler.removeFilter()           #为handler实例删除一个过滤器

3、Filter过滤器

Logger实例和Handler实例可以使用Filter实例来完成比级别更细颗粒度的过滤。Filter是一个过滤器基类,它只允许某个logger层级下的日志事件通过过滤。

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

比如一个filrer实例化时传递的name参数值为‘A.B’,那么该filter实例将只允许名称为类似如下规则的logger对象产生的日志通过过滤:‘A.B’、‘A.B.C’、‘A.B.D’、‘A.B.C.D’,而不允许‘A.BB’、‘B.A.B’等。如果name为空字符串,则运行所有的日志事件通过过滤。

import logging
filter = logging.Filter(name = '')

4、Formatter格式化器

Formatter对象用于配置日志信息的最终顺序、结构和内容。默认的时间格式为%Y-%m-%d %H:%M:%S。

import logging
formatter = logging.Formatter(fmt = None, datefmt = None)
#fmt:消息的格式化字符串,不指定则使用%(message)s
#datefmt:日期字符串,不指定则使用ISO8601日期格式,2018-03-13 15:30:08(%Y-%m-%d %H:%M:%S)

  

五、logging模块工作流程

1、logging模块使用过程

1)第一次导入logging模块或使用reload函数重新导入logging模块,logging模块中的代码将被执行,这个过程中将产生logging日志系统的默认配置。

2)自定义配置(可选)。logging标准模块支持三种配置方法:dictConfig、fileConfig、listen。其中,dictConfig通过一个字典进行配置Logger、Handler、Filter和Formatter;fileConfig通过一个文件进行配置;而listen则监听一个网络端口,通过接收网络数据进行配置。除了以上集体化配置外,也可以直接调用Logger、Handler等对象中的方法在代码中显式配置。

3)使用logging模块的全局作用域中的getLogger函数来得到一个Logger实例。

4)使用Logger实例中的Debug、Info等方法记录日志信息。

2、logging模块处理流程

1)(在用户代码中进行)日志记录函数调用,如:logger.info(...),logger.debug(...)等;
2)判断要记录的日志级别是否满足日志器设置的级别要求(要记录的日志级别要大于或等于日志器设置的级别才算满足要求),如果不满足则该日志记录会被丢弃并终止后续的操作,如果满足则继续下一步操作;
3)根据日志记录函数调用时掺入的参数,创建一个日志记录(LogRecord类)对象;
4)判断日志记录器上设置的过滤器是否拒绝这条日志记录,如果日志记录器上的某个过滤器拒绝,则该日志记录会被丢弃并终止后续的操作,如果日志记录器上设置的过滤器不拒绝这条日志记录或者日志记录器上没有设置过滤器则继续下一步操作--将日志记录分别交给该日志器上添加的各个处理器;
5)判断要记录的日志级别是否满足处理器设置的级别要求(要记录的日志级别要大于或等于该处理器设置的日志级别才算满足要求),如果不满足记录将会被该处理器丢弃并终止后续的操作,如果满足则继续下一步操作;
6)判断该处理器上设置的过滤器是否拒绝这条日志记录,如果该处理器上的某个过滤器拒绝,则该日志记录会被当前处理器丢弃并终止后续的操作,如果当前处理器上设置的过滤器不拒绝这条日志记录或当前处理器上没有设置过滤器测继续下一步操作;
7)如果能到这一步,说明这条日志记录经过了层层关卡允许被输出了,此时当前处理器会根据自身被设置的格式器(如果没有设置则使用默认格式)将这条日志记录进行格式化,最后将格式化后的结果输出到指定位置(文件、网络、类文件的Stream等);
8)如果日志器被设置了多个处理器的话,上面的第5-8步会执行多次;
9)这里才是完整流程的最后一步:判断该日志器输出的日志消息是否需要传递给上一级logger(之前提到过,日志器是有层级关系的)的处理器,如果propagate属性值为1则表示日志消息将会被输出到处理器指定的位置,同时还会被传递给parent日志器的handlers进行处理直到当前日志器的propagate属性为0停止,如果propagate值为0则表示不向parent日志器的handlers传递该消息,到此结束。

 

示例:

1、通过配置文件进行配置,使用fileConfig()函数读取配置文件

# -*- encoding:utf-8 -*-
import logging

# create logger
logger_name = "example"
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)

# create file handler
log_path = "./log.log"
fh = logging.FileHandler(log_path)
fh.setLevel(logging.WARN)

# create formatter
fmt = "%(asctime)-15s %(levelname)s %(filename)s %(lineno)d %(process)d %(message)s"
datefmt = "%a %d %b %Y %H:%M:%S"
formatter = logging.Formatter(fmt, datefmt)

# add handler and formatter to logger
fh.setFormatter(formatter)
logger.addHandler(fh)

# print log info
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')```

##### 文件配置
配置文件logging.conf如下:
```[loggers]
keys=root,example01

[logger_root]
level=DEBUG
handlers=hand01,hand02

[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0

[handlers]
keys=hand01,hand02

[handler_hand01]
class=StreamHandler
level=INFO
formatter=form01
args=(sys.stderr,)

[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form02
args=('log.log', 'a')


[formatters]
keys=form01,form02

[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s

[formatter_form02]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s```

使用程序logger.py如下:
```#!/usr/bin/python
# -*- encoding:utf-8 -*-
import logging
import logging.config

logging.config.fileConfig("./logging.conf")

# create logger
logger_name = "example"
logger = logging.getLogger(logger_name)

logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')```

  

 

 

参考信息:

https://www.jianshu.com/p/feb86c06c4f4

http://www.cnblogs.com/yyds/p/6901864.html

https://github.com/mugbya/Aurora/tree/logging

Python 3.5.4官方手册

posted on 2018-03-13 15:47  nicolas_Z  阅读(266)  评论(0)    收藏  举报

导航