先了解logging模块中的几个类
Logger:日志记录器,是应用程序中能直接使用的接口;
Handler:日志处理器,用以表明将日志保存到什么地方以及保存多久;
将(logger创建的)日志记录发送到合适的目的输出;
filter:提供了细度设备来决定输出哪条日志记录;用处不大
Formatter:格式化,用以配置日志的最终输出格式
logging.disable(logging.CRITICAL)#可以禁止该级别和以下级别的所有日志消息。
对于比较简单的脚本,可以直接使用basicConfig在代码中配置日志
importlogging
logging.basicConfig(level=logging.DEBUG,
format=%(asctime)s%(filename)s[line:%(lineno)d]%(levelname)s%(message)s,
datefmt=%a,%d%b%Y%H:%M:%S,
filename=/tmp/test.log,
filemode=w)
logging.debug(debugmessage)
logging.info(infomessage)
logging.warning(warningmessage)
logging.error(errormessage)
logging.critical(criticalmessage)
关于logging.basicConfig函数的常用配置:filename:指定日志文件名filemode:和file函数意义相同,指定日志文件的打开模式,w或adatefmt:指定时间格式,同time.strftime()level:设置日志级别,默认为logging.WARNING,即warning及以上级别的日志才输出stream:指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略
format:指定输出的格式和内容,format可以输出很多有用信息,如上例所示:%(name)s打印logger名,默认为root%(levelno)s:打印日志级别的数值%(levelname)s:打印日志级别名称%(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]%(filename)s:打印当前执行程序名%(funcName)s:打印日志的当前函数%(lineno)d:打印日志的当前行号%(asctime)s:打印日志的时间%(message)s:打印日志信息%(thread)d:打印线程ID%(threadName)s:打印线程名称%(process)d:打印进程ID
对于比较复杂的项目,可以将日志的配置保存到一个配置文件中
书里的例子如下:
在典型的使用场景中,一个日志记录器使用一个日志处理器,一个日志处理器使用一个日志格式化
[loggers]
keys=root
[handlers]
keys=logfile
[formatters]
keys=generic
[logger_root]
handlers=logfile
[handler_logfile]#定义handler输出日志的方式、日志文件的切换时间等
class=handers.TimeRotatingFileHandler
args=(app.log,midnight,1,10)
level=DEBUG
formatter=generic
[formatter_generic]#这个名字就是上面formatter+_+generic
format=%(asctime)s%(levelname)-5.5s[%(name)s:%(lineno)s]%(message)s
在[loggers]中声明了一个名为root的logger
在[handlers]中声明一个名为logfile的handler
在[formatters]中声明一个名为generic的formatter
在[logger_root]中定义root这个logger所使用的的handler,链接第1、2步
在[handler_logfile]中定义handler输出日志的方式、日志文件的切换时间等,链3
在[formatter_generic]中定义了日志的格式,包括日志产生的时间、日志的界别、
产生的日志的文件名和行号等信息。链接第5步
调用这个配置文件:logging.config.fileConfig(logging.cnf)
下面的内容出自博主杨小愚(多日志处理器、多日志格式化):
1:logging.getLogger([name])返回一个logger实例,如果没有指定name,返回rootlogger。只要name相同,返回的logger实例都是同一个而且只有一个,即name和logger实例是一一对应的。这意味着,无需把logger实例在各个模块中传递。只要知道name,就能得到同一个logger实例2:logger.setLevel(lvl)——设置logger的level,level有以下几个级别:NOTSETDEBUGINFOWARNINGERRORCRITICAL
#定义logger模块,root是父类,必需存在的,其它的是自定义。#logging.getLogger(NAME)就相当于向logging模块注册了实例化了#name中用.表示log的继承关系
[loggers]keys=root,example01,example02#[logger_xxxx]logger_模块名称#level级别,级别有DEBUG、INFO、WARNING、ERROR、CRITICAL#handlers处理类,可以有多个,用逗号分开#qualnamelogger名称,应用程序通过logging.getLogger获取。对于不能获取的名称,则记录到root模块。#propagate是否继承父类的log信息,0:否1:是
[logger_root]level=DEBUGhandlers=hand01,hand02[logger_example01]handlers=hand01,hand02qualname=example01propagate=0[logger_example02]handlers=hand01,hand03qualname=example02propagate=0
#[handler_xxxx]#classhandler类名#level日志级别#formatter,上面定义的formatter#argshandler初始化函数参数
[handlers]keys=hand01,hand02,hand03
[handler_hand01]
class=StreamHandler#Handler部分的内容在最下面(太长)level=INFOformatter=form02args=(sys.stderr,)
[handler_hand02]
class=FileHandlerlevel=DEBUGformatter=form01args=(myapp.log,a)
[handler_hand03]class=handlers.RotatingFileHandlerlevel=INFOformatter=form02args=(myapp.log,a,10**,5)
#日志格式[formatters]keys=form01,form02[formatter_form01]format=%(asctime)s%(filename)s[line:%(lineno)d]
%(levelname)s%(message)sdatefmt=%a,%d%b%Y%H:%M:%S[formatter_form02]format=%(asctime)s%(name)-12s:%(levelname)-8s%(message)sdatefmt=%a,%d%b%Y%H:%M:%S
3:logger.addHandler(hd)——logger雇佣handler来帮它处理日志handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输出到文件,还有些Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handlerhandler主要有以下几种:logging.StreamHandler:#日志输出到流即控制台,可以是sys.stderr、sys.stdoutlogging.FileHandler:#日志输出到文件logging.handlers.RotatingFileHandler#日志输出到文件,并按照设定的日志文件大小切割logging.handlers.TimedRotatingFileHandler#日志输出到文件,并按设定的时间切割日志文件logging.handlers.SocketHandler:#远程输出日志到TCP/IPsocketslogging.handlers.DatagramHandler:#远程输出日志到UDPsocketslogging.handlers.SMTPHandler:#远程输出日志到邮件地址logging.handlers.SysLogHandler:#日志输出到sysloglogging.handlers.NTEventLogHandler:#远程输出日志到WindowsNT//XP的事件日志logging.handlers.MemoryHandler:#日志输出到内存中的制定buffer由于StreamHandler和FileHandler是常用的日志处理方式,所以直接包含在logging模块中,而其他方式则包含在logging.handlers模块中,handle常见调用Handler.setLevel(lel)#指定被处理的信息级别,低于lel级别的信息将被忽略Handler.setFormatter()#给这个handler选择一个格式Handler.addFilter(filt)、Handler.removeFilter(filt):#新增或删除一个filter对象
各个Handler函数需要再细查,例如:TimedRotatingFileHandler