Python self-built logging module

Source: Internet
Author: User
Tags emit

This chapter describes the Python built-in module: The log module, for more information, refer to: Python Learning Guide

Simple to use

In the beginning, we experienced the basic function of logging with the shortest code.

import= logging.getLogger()logging.basicConfig()logger.setLevel('DEBUG')logger.debug('logsomething')#输出out>>DEBG:root:logsomething
    • The first step is to get a Loger object by using the Logging.getlogger function, but this object is temporarily unusable.
    • The second step, the Logging.basicconfig function, makes a series of default configurations, including format, handler, and so on.
    • In the third step, logger calls the Setlevel function to define the log level as debug
    • Finally, the debug function is called to output a debug-level message that is displayed on the standard output.
Log levels in the logging

Logging when generating the log, there is a logging level mechanism, which has the following log levels by default:

CRITICAL = 50ERROR = 40WARNING = 30INFO  20DEBUG = 10NOTEST = 0

Each logger object has a log level, which only outputs logs that are higher than it. If the level of a logger is info, then calling logger.debug () cannot output the log, and logger.warning () can output it.
In general, the above 6 log levels are perfectly enough for our daily use.

Basic classes in the logging

Logging is a basic Python module, and its source location in Python is as follows:

#主干代码/usr/lib/python2.7/logging/__init__.py#扩展的handler和config/usr/lib/pyhon2.7/logging/config.py/usr/lib/python2.7/loging/handlers.py

Several base classes that make up the backbone of logging are in __init__.py:

First base class LogRecord

A LogRecord object that corresponds to a row of data in the log. Typically includes: time, log level, message information, currently executing module, line number, function name ... This information is contained in a LogRecord object.
LogRecord objects can be imagined as a large dictionary:

class LogRecord(object):    #代表一条日志的类    def getMessage(self):        #获取self.msg    def markLogRecord(dict):    #这个方法很重要,生成一个空的LogRecord,然后通过一个字典,直接更新LogReocrd中的成员变量    = LogRecord(NoneNone""0""NoneNone)    rv.__dict__.update(dict)    return rv
The second base class formatter

The formatter object is used to define the log format, LogRecord saves a lot of information, but when we print the log we only need a few of them, formatter provides such a function, it relies on a Python function:

#通过字典的方式,输出格式化字符串print('%(name)s:%(num)d'%{'name':'my_name''num'100>>>my_name:100

If LogRecord is the dictionary behind, then formatter is the previous format string ... The abstract

The important code is as follows:

class  Formatter (object ): def  __init__  (self , Fmt=  none , datefmt =  none ): if  fmt: self . _fmt =  fmt else :  #默认的format  self . _fmt =  " % (message) s  "  def  format  (self , record)  #使用self. _fmt to format  s =  self . _fmt %  record.__dict__ return  s 
The third base class filter and Filterer

Filter class, the function is very simple. The Filter.filter () function passes in a LogRecord object, returns 1 by filtering, or returns 0. As you can see from the code, it's actually a filter for logrecord.name.

There is a list of filter objects in the Filterer class, which is an abstraction of a set of filter.

The important code is as follows:

classFilter (Object):def __init__( Self, name=''): Self. Name=Name Self. Nlen= Len(name)def Filter( Self, record):#返回1表示record通过, 0 means record does not pass        if  Self. Nlen== 0:return 1        elif  Self. Name==Record.name:return 1        #record. Name does not start with filter        elifRecord.name.find ( Self. Name,0, Self. Nlen)!= 0:return 0        #最后一位是否为        return(record.name[ Self. Nlen]== '.')classFilterer (Object):#这个类其实是定义了一个self. filters = [] List to manage multiple filter    defAddFilter ( Self,Filter):defRemovefilter ( Self,Filter):def Filter( Self, record):#使用列表中所有的filter进行筛选, any failure will return 0    #例如:        #filter. Name = ' A ', filter2.name= ' a.b ', Filter2.name = ' A, B, C '        #此时record. Name = ' A,b,c,d ' record to pass all filter filters
Advanced classes in the logging

With the above three basic classes, you can put together some of the more important advanced classes, the advanced class can realize the important functions of logging.

handler--abstracts the log output process.
    • The handler class inherits from Filterer. The handler class is an abstraction of the log output process.
    • While the handler class has a member variable self.level, the mechanism for logging levels discussed in the second section is implemented in handler.
    • Handler has a emit (record) function, which is responsible for outputting the log and must be implemented in handler subclasses.

The important code is as follows:

class  Handler (filterer): def  __init__         (self , Level =  notest)         #handler必须有level属性  self . Level =  _checklevel (level) def  format  (self , Record):  #使用self. Formatter, Formattercord  def  handler (self , Record):  #如果通过filter的 Filter, emit this log  RV =  self . filter         (record)        self . Emit (record) def  emit (self , record):  #等待子类去实现   

Next look at two simple handler subclasses, in which in the logging source code, there is a handler.py specifically defined a lot of complex handler, and some can be the log cache in memory, and some can do rotation, such as log.

Streamhandler
The simplest handler implementation, writes the log to a stream, the default stream is Sys.stderr

The important code is as follows:

class  Streamhandler ( Handler): def  __init__  (self , Stream =  none ): if  stream is  
    
     none : Stream 
     =  sys.stderr 
     self . Stre Am 
     =  stream 
     def  emit (
     self , record): 
     
       #将record的信息写入流  
       #处理一些编码的异常  fs 
      =  
       %s  \n   '   #每条日志都有换行  stream =  self . Stream Stream.Write (Fs%  msg) 
     
     

Filehandler
Output log to handler of file, inherit Streamhandler

The important code is as follows:

class FileHandler(StreamHandler):    def__init__(self, filename, mode='a')        #append方式打开一个文件        StreamHandler.__init__(selfself._open())    def emit(self, record):        #和streamhandler保持一致        StreamHandler.emit(self, record)
logger--a separate log pipeline

What is logger?
+ Logger class inherits from Filterer,
+ Logger object has logger.level log level
+ Logger Object Controls multiple handler:logger.handlers = []
+ Logger objects have a blessing word relationship

Simply put, logger this class, which concentrates all of our logrecord, filter classes, formatter classes, and handler classes. First, Logger generates a LogRecord read and write based on the input, passes the filter and formatter, and then sends the log out through all the handler in the Self.handlers list. There may be multiple handler in a logger, which can be achieved by placing a log in any position.

classLogger (Filterer):def __init__( Self, name, Level=Notest)#handler列表         Self. handlers=[] Self. level=_checklevel (Level)defAddHandler ( Self, HDLR):defRemoveHandler ( Self, HDLR):def_log ( Self, level, MSG, args, exc_info=None, extra=None):#在_log函数中创建了一个LogRecord对象Record=  Self. MakeRecord ( Self. Name, level, FN, Lno, msg, args, Exc_info, func, extra)#交给handle函数         Self. Handle (record)defHandle Self, Reord):#进行filter, and then call Callhandlers        if( not  Self. Disabled) and  Self.Filter(record): Self. Callhandlers (Record)defCallhandlers ( Self, record):#从当前logger到所有的父logger, recursive Handl incoming recordC=  Self         whileC: forHdlrinchC.handlers:hdlr.handle (Record)#进入handler的emit函数发送log.... c=C.parent
loggeradapter--an extension of the standard logger

LogRecord This large dictionary provides a lot of member variables, but if you still want to be able to get some more information when you output log, such as when you generate this log, call some functions to obtain additional information, you can add these to the logger The loggeradapter of this class plays a role.

Loggeradapter This class is very interesting, if you do not make any changes, then Loggeradapter class and Logger are no different. Loggeradapter just wrapped up the logger class.

The use of Loggeradapter is actually explained in the comments of its member function process ():

def process(self, msg, kwargs):    '''    Normally,you'll only need to overwrite this one method in a LoggerAdapter subclass for your specific needs.    '''

That is to say, rewrite the process function, here is an example:

ImportLoggingImportRandoml=Logging.getlogger (' name ')#定义一个函数, generate a random number of 0~1000defFunc ():returnRandom.randint (1, +)classMyLogger (logging. Loggeradapter):#继承LoggerAdapter, rewrite process, generate random number to add to MSG front    defProcess Self, Msg,kwargs):return '(%d),%s' %( Self. extra[' name '] (), msg), Kwargs#函数对象放入字典中传入LA=MyLogger (l,{' name ': func})#now, do some loggingLa.debug (' Some_loging_messsage ') out>>Debug:name: (167), Some_loging_messsage
Reference

Python Note _logging module (i)
Logging Code
Python Log Encapsulation
The logging module in Python

Python self-built logging module

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.