python logging - 高级

参考:

Advanced logging tutorial:https://docs.python.org/2.7/howto/logging.html#advanced-logging-tutorial

15.7. logging - Logging facility for Python:https://docs.python.org/2.7/library/logging.html?highlight=logging#module-logging

15.8. logging.config - Logging configuration:https://docs.python.org/2.7/library/logging.config.html

15.9. logging.handlers - Logging handlers:https://docs.python.org/2.7/library/logging.handlers.html


####################################################################


对于python的logging模块不了解的可以先查看文章:

python logging - 初级:http://blog.csdn.net/u012005313/article/details/51581442


logging模块有4个最关键的组件:Logging,Handler,Filter和Formatter

官方给出解释如下:

  • Loggers expose the interface that application code directly uses.
  • Handlers send the log records (created by loggers) to the appropriate destination.
  • Filters provide a finer grained facility for determining which log records to output.
  • Formatters specify the layout of log records in the final output.

使用logging模块时,首先需要得到一个Logger类的实例,称为记录器(logger)。每个记录器都有一个名字,并且logging模块是通过名字来管理这些记录器的,两个记录器之间可以通过命名空间的层次结构来确定关系(Each instance has a name, and they are conceptually arranged in a namespace hierarchy using dots (periods) as separators)。比如,名字为'one'的记录器就是名字为'one.two','one.three','one.four'的记录器的父辈,也就是说,使用点号(‘.’)来确定父子的关系。记录器的名字命名没有任何要求,你可以选择你喜欢的,但最好名字能够表明该记录器在程序中的作用。


可以使用getLogger函数来获取记录器,常用的是命名为模块名或文件名:

logger = logging.getLogger(__name__)


所有记录器(logger)的父辈是root记录器,它的名字就是“root”。


默认情况下,信息会被输出到控制台,默认的输出格式是logging.BASIC_FORMAT:

severity:logger name:message


这些可以通过函数basicConfig进行修改:

basicConfig(**kwargs)
函数功能:为整个日志系统进行基础配置(Do basic configuration for the logging system)

如果root记录器已经有处理器(handler)配置(关于处理器将在下文讲解),那么函数basicConfig将不会起作用。


可以使用以下的关键字参数:



如果在多线程中使用baskcConfig函数,那么该函数必须在主线程中使用。


####################################################

其流程图如下:




###################################################################33

下面讲解Logger,Handler以及Formatter的使用


Logger

记录器有三部分的功能:

1.它提供了一些方法(debug(),info(),warning(),error(),critical()等),供开发者使用

2.记录器依据自身等级或过滤器(filter)来判断是否生成信息(message)

3.记录器将信息发送到所有绑定到自身的处理器(handler)


记录器上最常用的方法可以分为两个部分:配置和信息发送


以下是最常用的配置方法:

1.Logger.setLevel():指定记录器能够处理信息的最低等级(he lowest-severity)。logging模块中,debug是最低的等级,critical是最高的等级。比如,设置记录器等级为INFO,那么该记录器能够处理INFO,WARNING,ERROR,CRITICAL的信息,而会忽略DEBUG等级的信息。

2.Logger.addHandler()和Logger.removeHandler():绑定处理器(handler)到指定的记录器上,以及解除绑定

3.Logger.addFilter()和Logger.removeFilter():绑定过滤器(filter)到指定的过滤器上,以及解除绑定


当记录器配置解除后,以下方法可以处理日志信息:

Logger.debug(),Logger.info(),Logger.warning(),Logger.error()和Logger.critical()函数:用于处理信息,同时设定了该信息的等级(level or severity),以便于记录器判断是否处理该信息


getLogger函数返回一个记录器实例的引用,多次使用该函数去引用相同名字的记录器实例将返回同一个记录器。

每个记录器都必须设定一个等级(level or severity)。但如果没有显式设定,那么会根据它的父辈的等级来进行设定;如果父辈也没有显式设定,那么继续查找父辈的父辈,依次类推-查找所有的父辈直到找到一个显式设置的等级。root记录器是所有记录器的父辈,它的等级默认为WARNING。


logging模块使用层次命名空间来管理所有记录器,从而设置了一个很好的方法。子记录器将会把信息传送给绑定在父记录器上的处理器(handler),因此,不需要为所有记录器配置处理器,只需要在父记录器上绑定处理器,那么子记录器的消息就能够通过该处理器进行处理(可以通过设置记录器的propagate属性为False来关闭向上传播,默认为True)。



################################################

Handler


处理器负责将信息发送到指定的地点。记录器可以绑定0个或者多个处理器(通过addHandler方法)。比如,我们需要将程序中的所有日志信息都保存在文件中,将等级在error及以上的信息发送到控制台,将所有的critical等级的信息都发送到email,那么,我们仅需定义3个不同的处理器,在处理器上指定这3个目的地即可。


通常我们并不直接使用Handler实例,而是引用它的子类。Handler作为一个基类定义了一些基本的函数,子类扩展另外的功能。常用的Handler子类有StreamHandlerFileHandler,另外,我们还会提到RotatingFileHandler详细的Handler子类)。


我们对Handler的使用的方法不多。常用在配置阶段:

1.setLevel:指定处理器能够处理的最低等级

2.setFormatter:绑定一个Formatter到处理器

3.addFilter和removeFilter


下面介绍常用的Handler子类:

class logging.StreamHandler(stream=None)
输出日志信息到控制台

class logging.FileHandler(filename, mode='a', encoding=None, delay=False)
输出日志信息到文件。常用的文件打开方式为添加信息。

class logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0)

输出日志信息到文件。需要设置文件所占的最大字节数(maxBytes)以及文件备份数(backupCount)。当前输入文件总是filename文件,比如,filename是'he.log',那么当该文件所占字节达到最大时,将he.log文件保存为he.log.1文件,如果已存在he.log.1文件,那么将其保存为he.log.2文件,依次类推,直到达到文件备份数为止,比如,backupCount=5,那么如果已存在he.log.5文件,则将其删除。


如果所有记录器(logger)均没有绑定处理器(handler),那么root记录器会默认生成一个输出到控制台的handler。


#################################3

Formatter


Formatter对象配置最终的日志的结构,顺序以及内容。它有两个可选参数:

logging.Formatter.__init__(fmt=None, datefmt=None)

默认的fmt格式是使用原始信息。默认的时间格式为:

%Y-%m-%d %H:%M:%S

#################################3

在设置等级(level or severity)时可以使用数字。logging模块内置了一些常数,如下表所示:




#################################

下面介绍logging的一些用法:


1.在多个线程中使用logging模块

logging模块是线程安全的,所以可以在多个线程中共同使用同一个logging实例。但是logging模块并不是进程安全的,在多个进程中使用可能会出现问题。


2.在多个模块中使用logging

module_a.py:

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import logging
import module_b

# 创建logger实例
logger = logging.getLogger('module_a')
logger.setLevel(logging.DEBUG)

# 创建流处理器
sh = logging.StreamHandler()
sh.setLevel(logging.DEBUG)

# 创建Formatter
formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')

# Formatter绑定在Handler上
sh.setFormatter(formatter)
# Handler绑定在logger上
logger.addHandler(sh)

logger.debug("this is debug")
logger.info("this is info")
module_b.hello()
logger.warn("this is warn")
logger.error("this is error")
modu = module_b.Clas()
modu.hi()
logger.critical("this is critical")

module_b.py:

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import logging

# create logger
logg = logging.getLogger('module_a.module_b')
logg.setLevel(logging.DEBUG)

class Clas:
	def __init__(self):
		logg.info("class: Clas")
		
	def hi(self):
		logg.debug("Clas -> hi")

def hello():
	logg.error("hello world")

结果:



如上图所示,子记录器('module_a.module_b')可以不用自己设置处理器,而调用父记录器绑定的处理器即可


修改如下可以使得结果更加直观易懂:

# 创建Formatter
formatter = logging.Formatter('%(asctime)s-%(name)20s-%(levelname)8s-%(message)s')

或者:

# 创建Formatter
formatter = logging.Formatter('%(asctime)s-%(name)-20s-%(levelname)-8s-%(message)s')


3.使用多个处理器和formatter

multiple_handlers_and_formatters.py:

绑定两个处理器,一个处理器将所有信息输出到控制台窗口,其信息格式为:

'%(asctime)s %(name)-6s: %(levelname)-8s: %(message)s'

另一个处理器将error等级及以上的信息输出到文件logging2.log,其信息格式为:

'%(levelname)-8s-%(message)s'

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import logging

# create logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# set StreamHandler
sh = logging.StreamHandler()
sh.setLevel(logging.DEBUG)

# set Formatter
formatter1 = logging.Formatter('%(asctime)s %(name)-6s: %(levelname)-8s: %(message)s')
sh.setFormatter(formatter1)

# set FileHandler
fh = logging.FileHandler("multi.log")
fh.setLevel(logging.ERROR)

# set Formatter
formatter2 = logging.Formatter('%(levelname)-8s-%(message)s')
fh.setFormatter(formatter2)

# add handlers to logger
logger.addHandler(sh)
logger.addHandler(fh)

# logging
logger.debug('debug message')
logger.info('info message')
logger.warn('warnning message')
logger.error('error message')
logger.critical('critical message')


结果:

控制台窗口:



multi.log:

ERROR   -error message
CRITICAL-critical message

还有一种更简便的方法,就是使用basicConfig函数:

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import logging

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)-6s: %(levelname)-8s: %(message)s')

# create logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# set FileHandler
fh = logging.FileHandler("multi.log")
fh.setLevel(logging.ERROR)

# set Formatter
formatter = logging.Formatter('%(levelname)-8s-%(message)s')
fh.setFormatter(formatter)

# add handlers to logger
logger.addHandler(fh)

# logging
logger.debug('debug message')
logger.info('info message')
logger.warn('warnning message')
logger.error('error message')
logger.critical('critical message')


能够达到同样的效果


4.使用FileRotationHandler处理器

代码如下:

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import glob
import logging
import logging.handlers

LOG_FILENAME = 'rotation/logging_rotatingfile_example.out'

# set up a specific logger with our desired output level
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)

# add the log message handler to the logger
handler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=20, backupCount=5)

my_logger.addHandler(handler)

# log some messages
for i in range(20):
	my_logger.debug('i = %d'%i)
	
# see what files are created
logfiles = glob.glob('%s*'%LOG_FILENAME)

for filename in logfiles:
	print filename

在这里设置单个文件的最大容量为20字节,设置5个备份文件(所以共有6个文件)

rotation文件夹内:


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值