python模块---logging(日志管理)
一般情况下,一些程序的调试过程中我们会让它输出一些信息,特别是一些大型的程序,我们通过这些信息可以了解程序的运行情况,python提供了一个日志模块logging,它可以把我们想要的信息全部保存到一个日志文件中,方面我们查看。最近做的项目,有一些业务处理逻辑是先将数据写入队列,然后通过python读取队列中的内容,继续处理后续的逻辑。因为队列消费一次就没了,所以做好日志记录格外重要;
test_log1.py
#! /usr/bin/python import logging LOG_FILENAME="log_test.txt" logging.basicConfig(filename=LOG_FILENAME,level=logging.NOTSET) logging.debug("This message should go to the log file") LOG_FILENAME_22="log_test22.txt" logging.basicConfig(filename=LOG_FILENAME_22,level=logging.DEBUG) logging.debug("This message 222should go to the log file")
执行结果:
只生成了一个log_test.txt文件,文件内容是:
DEBUG:root:This message should go to the log file
DEBUG:root:This message 222should go to the log file
而没有生成log_test22.txt文件.
原因:查看logging的文档:
FUNCTIONS addLevelName(level, levelName) Associate 'levelName' with 'level'. This is used when converting levels to text during message formatting. basicConfig(**kwargs) Do basic configuration for the logging system. This function does nothing if the root logger already has handlers configured. It is a convenience method intended for use by simple scripts to do one-shot configuration of the logging package. The default behaviour is to create a StreamHandler which writes to sys.stderr, set a formatter using the BASIC_FORMAT format string, and add the handler to the root logger. A number of optional keyword arguments may be specified, which can alter the default behaviour. filename Specifies that a FileHandler be created, using the specified filename, rather than a StreamHandler. filemode Specifies the mode to open the file, if filename is specified (if filemode is unspecified, it defaults to 'a'). format Use the specified format string for the handler. datefmt Use the specified date/time format. level Set the root logger level to the specified level. stream Use the specified stream to initialize the StreamHandler. Note that this argument is incompatible with 'filename' - if both are present, 'stream' is ignored.
test_log2.py
>>> import logging >>> logger=logging.getLogger() >>> handler=logging.FileHandler("Log_test.txt") >>> logger.addHandler(handler) >>> logger.setLevel(logging.NOTSET) >>> logger.error("This is an error message") >>> logger.info("This is an info message") >>> logger.critical("This is a critical message")
日志文件中会出现三行内容:
This is an error message
This is an info message
This is a critical message
上面程序的第2行是生成一个日志对象,里面的参数时日志的名字,可以带,也可以不带。
第3行是生成了一个handler,logging支持很多种Handler,像FileHandler,SocketHandler等待,这里由于我们要写文件,所以用了FileHandler,它的参数就是filename,默认当前路径,当然我们可以自己指定路径。
第5行设置日志信息输出的级别。Logging提供了多种日志级别,如NOTSET,DEBUG,INFO,WARNING,ERROR,CRITICAL等,每个级别都对应一个数值,如果我们不自己设置输出级别,那么系统会执行缺省级别,值为30,就warning。Logging也提供了一个方法来查看缺省日志级别,getLevelName(logger,getEffectiveLevel())。
如果想将写入日志的这个功能抽象出一个方法出来,并且能够制定不同的日志写入不同的文件里,如,
test_log3.py
#! /usr/bin/python import logging def setLog(log_filename,log_message): logger=logging.getLogger() handler=logging.FileHandler(log_filename) logger.addHandler(handler) logger.setLevel(logging.NOTSET) logger.debug(log_message) # 如果没有此句话,则会将同一个message追加到不同的log中 logger.removeHandler(handler) if __name__ =='__main__': setLog('Log_test','it all right') setLog('Log_test88','it all righ8888t') setLog('Log_test99','it all righ999t')
上面最重要的是:logger.removeHandler(handler),没有了这行code,'it all righ8888t'会写入到Log_test文件中;
日志对象对于不同的级别信息提供不同的函数进行输出,如:info(), error(), debug()等。当写入日志时,小于指定级别的信息将被忽略。因此为了输出想要的日志级别一定要设置好此参数。这里我设为NOTSET(值为0),也就是想输出所有信息。系统默认的日志级别排序为,CRITICAL,ERROR,WARNING,INFO,DEBUG,NOTSET。比如说我们要输出的信息为CRITICAL,但是我们的日志级别为DEBUG,那么这个信息将被忽略掉。我们看下面的例子:
test_log4.py
#! /usr/bin/python # -*- coding: utf-8 -*- import logging import sys LEVELS={'debug':logging.DEBUG, 'info':logging.INFO, 'warning':logging.WARNING, 'error':logging.ERROR, 'critical':logging.CRITICAL} if len(sys.argv)>1: level_name=sys.argv[1] level=LEVELS.get(level_name,logging.NOTSET) logging.basicConfig(level=level) logging.debug("This is a debug message") logging.info("This is an info message") logging.warning("This is a warning message") logging.error("This is an error message") logging.critical("This is a critical error message")
执行结果:
可以看到过滤进行的很明显。当我们设置级别最低位debug时,所有的信息都输出了,当我们设为最高位critical时候,只有critical输出了,低于critical的被过滤了。
Logging是非常有用的,一个程序的健壮性也这个有关,当一个程序包含很多的调试信息时,可以方便我们发现问题,发现错误。