1. 定义
Python的logging模块提供了通用的日志系统,可以方便第三方模块或者应用使用。这个模块提供不同的日志级别,并可以采用不同的方式记录日志。
Java中的日志模块是Log4j,python的logging模块和它类似。
2. 组成
logging主要由三个部分组成:logger、handle、formatter
- logger用来获取日志对象
- handler用来设置日志输出的方向
- formatter用来设置日志内容的格式
logger:
logger=logging.getLogger('name')
handler:
handler1=logging.FileHandler('log path') #输出到日志文件 handler2=logging.StreamHandler(sys.stderr) #输出到控制台
formatter:
formatter=logging.Formatter('%(asctime)s...')
定义完三个主要组成部分后,需要关联这三个部分:
handler1.setFormatter(formatter) #把handle和formatter绑定在一起 logger.addHandle(handler1) #logger和handle绑定在一起
3.细节
3.1 logger
logging.getLogger(),是一个顶级父对象,没有指定name时返回root looger
logging.getLogger('a'),是顶级父对象的子对象
logging.getLogger('a.b'),是a对象的子对象
设置basicConfig
logging.basicConfig(path,level,filemode,format) #把handler配置好了,日志级别设置好了,输出格式配置好了
logging.basicConfig(filename=os.path.join(os.getcwd(),'log.txt'),level=logging.WARN,filemode='w',format='%(asctime)s-%(levelname)s:%(message)s')
3.2 handler
logging模块常用三个handler:
logging.StreamHandler(stream=None) #日志信息会输出到指定的stream中,如果stream为空则默认输出到sys.stderr,也可设置sys.__stdout__
logging.FileHandler(filename, mode='a', encoding=None, delay=False) #默认情况下,日志文件可以无限增大
logging.NullHandler #空操作
logging其他的handler:
logging.handlers.WatchedFileHandler(filename, mode='a', encoding=None, delay=False)
用于监视文件的状态,如果文件被改变了,那么就关闭当前流,重新打开文件,创建一个新的流。这个handler是专门为linux/unix系统设计的,因为在windows系统下,正在被打开的文件是不会被改变的
logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0)
参数maxBytes和backupCount允许日志文件在达到maxBytes时rollover.当文件大小达到或者超过maxBytes时,就会新创建一个日志文件。backupcount是备份数目,也就是最多能有多少个备份
logging.handlers.TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False)
定时循环日志handler,位于logging.handlers,支持定时生成新日志文件。参数when决定了时间间隔的类型,参数interval决定了多少的时间间隔。如when=‘D’,interval=2,就是指两天的时间间隔,backupCount决定了能留几个日志文件。超过数量就会丢弃掉老的日志文件
'S' | 秒 'M' | 分 'H' | 时 'D' | 天 'W0'-'W6' | 周一至周日 'midnight' | 每天的凌晨
其他handler具体参加官方文档其他handlers
3.3 formatter
用于设置日志信息的规则、结构、内容,默认的时间格式为%Y-%m-%d %H:%M:%S
%(name)s |
Logger的名字 |
%(levelno)s |
数字形式的日志级别 |
%(levelname)s |
文本形式的日志级别 |
%(pathname)s |
调用日志输出函数的模块的完整路径名,可能没有 |
%(filename)s |
调用日志输出函数的模块的文件名 |
%(module)s |
调用日志输出函数的模块名 |
%(funcName)s |
调用日志输出函数的函数名 |
%(lineno)d |
调用日志输出函数的语句所在的代码行 |
%(created)f |
当前时间,用UNIX标准的表示时间的浮 点数表示 |
%(relativeCreated)d |
输出日志信息时的,自Logger创建以 来的毫秒数 |
%(asctime)s |
字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒 |
%(thread)d |
线程ID。可能没有 |
%(threadName)s |
线程名。可能没有 |
%(process)d |
进程ID。可能没有 |
%(message)s |
用户输出的消息 |
一般格式 '%(asctime)s-%(name)s-%(levelname)s-%(message)s'
3.4 设置日志级别
logger和handler在设置日志级别之前都有默认的日志级别,logging.getLogger()默认的level是logging.WARNING,低于该级别的就不输出了,可以修改日志级别
logging.getLogger().level=logging.DEBUG
logging.getLogger().setLevel(logging.DEBUG)或logging.FileHandler('').setLevel(logging.DEBUG)
logging.NOTSET<logging.DEBUG<logging.INFO<logging.WARNING<logging.Error<logging.CRITICAL
对应数字 0<10<20<30<40<50
3.5 输出日志级别
输出日志
logging.getLogger().info('输出内容')
logging.getLogger().debug('')
logging.getLogger().warning('')
logging.getLogger().error('')
logging.getLogger().notset('')
4. 例子
import logging
#创建一个logger
logger=logging.getLogger('mylogger')
logger.setLevel(logging.DEBUG)
#创建一个handler,用于写入日志文件
fh=logging.FileHandler('test.log')
fh.setLevel(logging.DEBUG)
#再创建一个handler,用于输出到控制台
ch=logging.StreamHandler()
ch.setLevel(logging.DEBUG)
#定义handler的输出格式
formatter=logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
#给logger添加handler
logger.addHandler(fh)
logger.addHandler(ch)
#记录一条日志
logger.info('foorbar')
运行后,再控制台和日志文件都有一条日志:
2011-08-31 19:18:29,816-mylogger-INFO-foorbar
-----------------------------------------------------------------------------------------------------
例子1:
import logging
logging.error('xxx')
这种是用python默认的logger名字为root的日志,输出到日志中的形式是ERROR:root:xxx 。
默认设置为 logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
例子2:
import logging
logger=logging.getLogger('define')
file_handler=logging.FileHandler(os.path.join(os.path.dirname(__file__),'auto.log'))
logger.addHandler(file_handler)
logger.setLevel(logging.DEBUG) #logger作为‘母’设置了日志等级
console=logging.StreamHandler()
console.setLevel(logging.DEBUG) #console作为‘子’设置比logger等级更高的level,不设置则继承‘母’的日志等级
formatter=logging.Formatter('%(message)s') #设置‘母’的输出格式
console.setFormatter(formatter)
logger.addHandler(console)
logger.info('this is a logger info')
logger.debug('this is a logger debug')
logger.error('this is a logger error')
filehandler和consolehandler都遵从logging的设置
例子2:
其他py文件若想跟主py文件输出的日志放到一个文件中,则需要在次py文件中获取主py文件定义的logger,logger=logging.getLogger('define')