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