在 python 中,logging
有几个关键的类,分别是 Logger
、Handler
、Filter
和 Formatter
,理解好他们的关系,对于日志理解就不好那么杂乱了,他们之间的关系可以表示为:
图 1:Logger 关系图 |
Logger
是我们直接拿来打日志的,例如logger.info("hello")
Handler
是说日志打到哪里去,是打印到控制台,还是打印到文件等等。Filter
虽然Handler
有简单的 level 过滤,但是有时需要更复杂的过滤可能就会使用它Formatter
我们的日志打印出来的样式是怎样的,时间改怎么显示等等就是Formatter
的责任
Logger
的 level
的话,python 是有这么几个 level
的:按照日志级别大小关系为CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET,当然也可以自己定义日志级别。
下面就讲解几个例子来深化这些概念:
1. 默认的配置
>>> import logging
>>> logging.getLogger().warning("hehe")
No handlers could be found for logger "root"
跑一遍之后会发现打印出来的并不是 “hehe”,什么都没有,我的 pyhton 环境是 python 2.7.11
,默认情况下,logging 的默认 logger 是没有 handler 的,所以日志是打不出来的。
2. 配置打印到文件
import logging
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='myapp.log',
filemode='w')
logging.debug('This is debug message')
这里用的是 logging 的 basicConfig
,它默认配置的是一个叫做 ‘root
‘ 的 Logger
,可以看到他的参数,level
是 DEBUG
级别,然后配置了日志格式和时间格式,因为是输出到文件,所以还要指定文件的位置以及打开模式。我们打开文件 ./myapp.log
,可以看到文件中内容为:
Fri, 09 Sep 2016 17:40:34 <stdin>[line:1] INFO hehe
logging.basicConfig函数各参数含义见附录一。
3. 配置日志输出到控制台
import logging
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
logging.debug('This is debug message')
可以看到,这里显式得创建了一个 StreamHandler 和 Formatter,然后设置 Level 和 formatter,然后将它加入到 Logger 中。我们可以在屏幕上看到输出:
root : WARNING This is debug message
4. 配置日志回滚
import logging
from logging.handlers import RotatingFileHandler
#定义一个RotatingFileHandler,最多备份5个日志文件,每个日志文件最大10M
Rthandler = RotatingFileHandler('myapp.log', maxBytes=10*1024*1024,backupCount=5)
Rthandler.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
Rthandler.setFormatter(formatter)
logging.getLogger('').addHandler(Rthandler)
这里其实是 logging 中的一个特殊的 Handler,叫 RotatingFileHandler,然后其他各方面都和刚才的 Handler 一致,不过还多了一个,就是文件的最大 size 以及回滚文件的个数。除了 RotatingFileHandler
之外,我们还可以考虑使用 TimedRotatingFileHandler
。
logging的几种handle方式如下:
- logging.StreamHandler: 日志输出到流,可以是sys.stderr、sys.stdout或者文件
- logging.FileHandler: 日志输出到文件
更多的 Handler 可以参考附录二。
5.通过文件配置日志
我们上面的例子都是在代码中对 logger 进行配置的,其实,除了在代码中配置之外,还可以在配置文件中配置好这一切,配置文件是 python 原生支持的 ini 配置文件。
由于配置文件太长,所以我以 附件 的形式给出,如有需要开在新窗口打开查看。然后看下使用示例:
import logging
import logging.config
logging.config.fileConfig(logger.conf)
logger = logging.getLogger(example01)
logger.warning('This is warning message')
6. 附录
附录一
logging.basicConfig 各参数含义:
- filename: 指定日志文件名
- filemode: 和file函数意义相同,指定日志文件的打开模式,’w’或’a’
- format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:
- %(levelno)s: 打印日志级别的数值
- %(levelname)s: 打印日志级别名称
- %(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
- %(filename)s: 打印当前执行程序名
- %(funcName)s: 打印日志的当前函数
- %(lineno)d: 打印日志的当前行号
- %(asctime)s: 打印日志的时间
- %(thread)d: 打印线程ID
- %(threadName)s: 打印线程名称
- %(process)d: 打印进程ID
- %(message)s: 打印日志信息
- datefmt: 指定时间格式,同time.strftime()
- level: 设置日志级别,默认为logging.WARNING
- stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略
附录二
logging.handlers
中的更多 Handler
:
- logging.handlers.BaseRotatingHandler
- logging.handlers.RotatingFileHandler
- logging.handlers.TimedRotatingFileHandler
- logging.handlers.SocketHandler: 远程输出日志到TCP/IP sockets
- logging.handlers.DatagramHandler: 远程输出日志到UDP sockets
- logging.handlers.SMTPHandler: 远程输出日志到邮件地址
- logging.handlers.SysLogHandler: 日志输出到syslog
- logging.handlers.NTEventLogHandler: 远程输出日志到Windows NT/2000/XP的事件日志
- logging.handlers.MemoryHandler: 日志输出到内存中的制定buffer
- logging.handlers.HTTPHandler: 通过GET或POST远程输出到HTTP服务器
由于 StreamHandler
和 FileHandler
是常用的日志处理方式,所以直接包含在 logging
模块中,而其他方式则包含在 logging.handlers
模块中。