Python日志模块logging
logging是Python自带的日志系统, 使用方便灵活.
示例, 将警告输出到终端:
>>>import logging
>>>logging.warning('This is warning message')
WARNING:root:This is warning message
我们可以自定义logger来向文件和终端写日志, 并重设了日志的格式:
import logging
logger = logging.getLogger("service log")
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler('log/info.log', 'a')
fh.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', "%Y-%m-%d %H:%M:%S")
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger.addHandler(fh)
logger.addHandler(ch)
写入日志:
>>>logger.info("admin login success")
2017-02-21 11:58:42 - service log - INFO - admin login success
logging
logging模块主要提供了四个类:
logger提供了应用程序可以直接使用的接口;
handler将(logger创建的)日志记录发送到合适的输出通道;
filter决定输出哪条日志记录;
formatter决定日志记录的最终输出格式;
这里提供一个
logger
logger默认提供5个级别的日志输出, 从高到低为:
logger.critical(msg)
logger.error(msg)
logger.warning(msg)
logger.info(msg)
logger.debug(msg)
logger只输出高于或等于当前级别的日志, logging的root logger默认级别为info.
>>> log = logging.getLogger()
>>> log.setLevel(logging.INFO)
>>> logging.INFO
20
logger可以添加handler, filter和formatter以增强功能:
Logger.addHandler(handler)
Logger.removeHandler(handler)
Logger.addFilter(filter)
Logger.removeFilter(filter)
handler
Handler把Logger记录发到相应的通道, logging中提供了常用的几个Handler:
StreamHandler 发送日志到终端输出流中
FileHandler 发送日志到日志文件中
NullHandler 无操作的日志处理类
将日志输出到文件:
>>> logger = logging.getLogger()
>>> fh = logging.FileHandler('test.log', 'w')
>>> logger.addHandler(fh)
>>> logger.warning('This is warning message')
WARNING:root:This is warning message
~$ cat test.log
This is warning message
其它的Handlers在logging.handlers中:
- RotatingFileHandler 在一个日志文件到达最大字数后建立新的文件记录日志
- TimedRotatingFileHandler 发生日志到文件,并在适当的事件间隔进行轮徇
- SocketHandler 通过TCP协议发送日志
- DatagramHandler 通过UDP协议发送日志
- SysLogHandler 发送日志到UNIX syslog服务,并支持远程syslog服务
- NTEventLogHandler 发送日志到WindowsNT/2000/XP事件日志
- SMTPHandler 通过SMTP协议发送日志
- MemoryHandler 发送日志到内存中的缓冲区,并在达到特定条件时清空
- HTTPHandler 通过GET或POST方法发送日志到HTTP服务器
Formatter
Formatter对象设置日志信息的格式, 示例:
>>> logger = logging.getLogger()
>>> handler = logging.StreamHandler()
>>> formatter = logging.Formatter('%(name)-6s: %(levelname)-8s %(asctime)-8s %(message)s')
>>> handler.setFormatter(formatter)
>>> logger.addHandler(handler)
>>> logger.warning('This is warning message')
WARNING:root:This is warning message
root : WARNING 2016-06-07 21:48:57,801 This is warning message
第二行信息即为新增Formatter输出的没,这里没有移除原有Formatter所以输出了两条信息.
Formatter的标识符如下表所示:
%(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 | 用户输出的消息 |
Filter
logging.getLogger()时参数的格式类似于“A.B.C”, 这样做也便于Filter的配置.名为“A.B”的过滤器只让名字带有 “A.B”前缀的Logger输出信息.
>>>import logging
>>>logger = logging.getLogger('cn.finley')
>>>handler = logging.StreamHandler()
>>>filter = logging.Filter('cn.finley')
>>>handler.addFilter(filter)
>>>logger.addHandler(handler)
>>>logger.warning('This is warning message')
>>>
>>>fake_logger = logging.getLogger('cn.fakefinley')
>>>handler = logging.StreamHandler()
>>>filter = logging.Filter('cn.finley')
>>>handler.addFilter(filter)
>>>fake_logger.addHandler(handler)
>>>fake_logger.warning('This is warning message')
This is warning message
可以看到fake_logger
的输出被拦截
模块方法
logging模块提供了root logger.
logging模块也提供了一系列模块方法:
logging.getLogger([name]) 根据config返回指定的logger, 默认返回root logger
logging.basicConfig(): 用默认Formatter为日志系统建立一个StreamHandler,设置baseConfig并加到root logger中
logging.debug(), logging.info(), logging.warning(), logging.error()、logging.critical()可以直接通过root logger输出日志信息.
logging.basicConfig
basicConfig方法提供对RootHandler的基本配置,示例:
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.config
logging.config模块可以通过文件配置logger, 先展示配置文件:
#logger.conf
###############################################
[loggers]
keys=root,example01,example02
[logger_root]
level=DEBUG
handlers=hand01,hand02
[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0
[logger_example02]
handlers=hand01,hand03
qualname=example02
propagate=0
###############################################
[handlers]
keys=hand01,hand02,hand03
[handler_hand01]
class=StreamHandler
level=INFO
formatter=form02
args=(sys.stderr,)
[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form01
args=('myapp.log', 'a')
[handler_hand03]
class=handlers.RotatingFileHandler
level=INFO
formatter=form02
args=('myapp.log', 'a', 10*1024*1024, 5)
###############################################
[formatters]
keys=form01,form02
[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
datefmt=%a, %d %b %Y %H:%M:%S
[formatter_form02]
format=%(name)-12s: %(levelname)-8s %(message)s
datefmt=
使用.conf文件配置logger:
>>> import logging
>>> import logging.config
>>>
>>> logging.config.fileConfig("logger.conf")
>>> logger = logging.getLogger("example01")
>>>
>>> logger.debug('This is debug message')
>>> logger.info('This is info message')
example01 : INFO This is info message
>>> logger.warning('This is warning message')
example01 : WARNING This is warning message